From 2887aedc3c94d7ce1cf2687c2fa4553f9e1fbb57 Mon Sep 17 00:00:00 2001 From: Stepan Usatiuk Date: Tue, 13 Oct 2020 23:58:49 +0300 Subject: [PATCH] (hopefully) working photos upload backend --- .gitignore | 5 +- .vscode/settings.json | 5 +- frontend/src/Photos/Overview.tsx | 2 +- package-lock.json | 398 ++++++++++++++++++++++++--- package.json | 18 +- src/app.ts | 36 ++- src/config/index.ts | 28 +- src/entity/Photo.ts | 88 ++++++ src/entity/User.ts | 25 ++ src/routes/dev.ts | 4 +- src/routes/photos.ts | 233 +++++++++++++++- src/routes/users.ts | 44 +-- src/tests/integration/photos.test.ts | 298 ++++++++++++++++++++ src/tests/integration/photos/cat.jpg | Bin 0 -> 58332 bytes src/tests/integration/photos/dog.jpg | Bin 0 -> 67292 bytes src/tests/integration/users.test.ts | 87 ++++-- src/tests/integration/util.ts | 50 +++- src/types.ts | 14 +- src/util.ts | 24 ++ 19 files changed, 1255 insertions(+), 104 deletions(-) create mode 100644 src/tests/integration/photos.test.ts create mode 100644 src/tests/integration/photos/cat.jpg create mode 100644 src/tests/integration/photos/dog.jpg create mode 100644 src/util.ts diff --git a/.gitignore b/.gitignore index 5c325f3..49a546a 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,7 @@ ormconfig.dev.json ormconfig.test.json .env .directory -.history \ No newline at end of file +.history +data_test +data_dev +data \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 6e150f8..14a02e0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,5 +5,8 @@ "eslint.workingDirectories": [ ".", "./frontend" - ] + ], + "search.exclude": { + "**/package-lock.json": true + } } \ No newline at end of file diff --git a/frontend/src/Photos/Overview.tsx b/frontend/src/Photos/Overview.tsx index e476aa3..142a264 100644 --- a/frontend/src/Photos/Overview.tsx +++ b/frontend/src/Photos/Overview.tsx @@ -8,7 +8,7 @@ export interface IOverviewComponentProps { fetching: boolean; spinner: boolean; - fetchDocs: () => void; + fetchPhotos: () => void; } export function OverviewComponent() { diff --git a/package-lock.json b/package-lock.json index ab10df4..b1fc1ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -79,6 +79,33 @@ "vary": "^1.1.2" } }, + "@koa/router": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/@koa/router/-/router-9.4.0.tgz", + "integrity": "sha512-dOOXgzqaDoHu5qqMEPLKEgLz5CeIA7q8+1W62mCvFVCOqeC71UoTGJ4u1xUSOpIl2J1x2pqrNULkFteUeZW3/A==", + "requires": { + "debug": "^4.1.1", + "http-errors": "^1.7.3", + "koa-compose": "^4.1.0", + "methods": "^1.1.2", + "path-to-regexp": "^6.1.0" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "@nodelib/fs.scandir": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", @@ -180,6 +207,12 @@ "@types/node": "*" } }, + "@types/deasync": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@types/deasync/-/deasync-0.1.1.tgz", + "integrity": "sha512-/AsDEUsHjyzMX0UjPgysggxFO8r7//c4aS9aeQwHzgs5POBsqaBFWW9+KYFGUyx/VYT4HrT/+JzAGTEEL2d4OQ==", + "dev": true + }, "@types/eslint": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.3.tgz", @@ -318,15 +351,6 @@ "@types/koa": "*" } }, - "@types/koa-router": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/koa-router/-/koa-router-7.4.1.tgz", - "integrity": "sha512-Hg78TXz78QYfEgdq3nTeRmQFEwJKZljsXb/DhtexmyrpRDRnl59oMglh9uPj3/WgKor0woANrYTnxA8gaWGK2A==", - "dev": true, - "requires": { - "@types/koa": "*" - } - }, "@types/koa-send": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/@types/koa-send/-/koa-send-4.1.2.tgz", @@ -364,18 +388,42 @@ "@types/koa": "*" } }, + "@types/koa__router": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@types/koa__router/-/koa__router-8.0.3.tgz", + "integrity": "sha512-eS8K49z1x6OaW1ha61kRksVo42L5DWdQUA3kVpH1Kz6TuKBlG0ri42ELA4zSh+xg+6fAqjfuWA7bfNvwVMNXQA==", + "dev": true, + "requires": { + "@types/koa": "*" + } + }, "@types/mime": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==", "dev": true }, + "@types/mime-types": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz", + "integrity": "sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM=", + "dev": true + }, "@types/mocha": { "version": "8.0.3", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.0.3.tgz", "integrity": "sha512-vyxR57nv8NfcU0GZu8EUXZLTbCMupIUwy95LJ6lllN+JRPG25CwMHoB1q5xKh8YKhQnHYRAn4yW2yuHbf/5xgg==", "dev": true }, + "@types/mysql": { + "version": "2.15.15", + "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.15.tgz", + "integrity": "sha512-1GJnq7RwuFPRicMHdT53vza5v39nep9OKIbozxNUpFXP04CydcdWrqpZQ+MlVdlLFCisWnnt09xughajjWpFsw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/node": { "version": "14.11.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.5.tgz", @@ -414,6 +462,15 @@ "@types/mime": "*" } }, + "@types/sharp": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.26.0.tgz", + "integrity": "sha512-oJrR8eiwpL7qykn2IeFRduXM4za7z+7yOUEbKVtuDQ/F6htDLHYO6IbzhaJQHV5n6O3adIh4tJvtgPyLyyydqg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", @@ -895,6 +952,36 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==" }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bl": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz", + "integrity": "sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1299,6 +1386,15 @@ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, + "color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz", + "integrity": "sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==", + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.4" + } + }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -1312,6 +1408,15 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, + "color-string": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.4.tgz", + "integrity": "sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -1536,6 +1641,22 @@ } } }, + "deasync": { + "version": "0.1.20", + "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.20.tgz", + "integrity": "sha512-E1GI7jMI57hL30OX6Ht/hfQU8DO4AuB9m72WFm4c38GNbUD4Q03//XZaOIHZiY+H1xUaomcot5yk2q/qIZQkGQ==", + "requires": { + "bindings": "^1.5.0", + "node-addon-api": "^1.7.1" + }, + "dependencies": { + "node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==" + } + } + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", @@ -1549,6 +1670,14 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, + "decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "requires": { + "mimic-response": "^2.0.0" + } + }, "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", @@ -1674,6 +1803,14 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, "enquirer": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", @@ -2024,6 +2161,11 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, "external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -2101,6 +2243,11 @@ "flat-cache": "^2.0.1" } }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -2168,6 +2315,11 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, "fs-minipass": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", @@ -2260,6 +2412,11 @@ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==" }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" + }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -2357,6 +2514,15 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, + "hasha": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", + "requires": { + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + } + }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -2697,6 +2863,11 @@ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz", "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==" }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" + }, "is-string": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", @@ -2934,33 +3105,6 @@ } } }, - "koa-router": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/koa-router/-/koa-router-9.4.0.tgz", - "integrity": "sha512-RO/Y8XqSNM2J5vQeDaBI/7iRpL50C9QEudY4d3T4D1A2VMKLH0swmfjxDFPiIpVDLuNN6mVD9zBI1eFTHB6QaA==", - "requires": { - "debug": "^4.1.1", - "http-errors": "^1.7.3", - "koa-compose": "^4.1.0", - "methods": "^1.1.2", - "path-to-regexp": "^6.1.0" - }, - "dependencies": { - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, "koa-send": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/koa-send/-/koa-send-5.0.1.tgz", @@ -3294,6 +3438,11 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" }, + "mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -3332,6 +3481,11 @@ "minimist": "^1.2.5" } }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, "mocha": { "version": "8.1.3", "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.1.3.tgz", @@ -3487,6 +3641,11 @@ "thenify-all": "^1.0.0" } }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -3527,6 +3686,21 @@ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" }, + "node-abi": { + "version": "2.19.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.19.1.tgz", + "integrity": "sha512-HbtmIuByq44yhAzK7b9j/FelKlHYISKQn0mtvcBrU5QBkhoCMp5bu8Hv5AI34DcKfOAcJBcOEMwLlwO62FFu9A==", + "requires": { + "semver": "^5.4.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, "node-addon-api": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.0.2.tgz", @@ -3556,6 +3730,11 @@ } } }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" + }, "nopt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", @@ -3924,6 +4103,40 @@ "semver-compare": "^1.0.0" } }, + "prebuild-install": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.5.tgz", + "integrity": "sha512-YmMO7dph9CYKi5IR/BzjOJlRzpxGGVo1EsLSUZ0mt/Mq0HWZIHOKHHcHdT69yG54C9m6i45GpItwRHpk0Py7Uw==", + "requires": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp": "^0.5.1", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.7.0", + "noop-logger": "^0.1.1", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0", + "which-pm-runs": "^1.0.0" + }, + "dependencies": { + "simple-get": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", + "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "requires": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + } + } + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4241,6 +4454,15 @@ "iterate-value": "^1.0.0" } }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -4532,6 +4754,22 @@ "safe-buffer": "^5.0.1" } }, + "sharp": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.26.1.tgz", + "integrity": "sha512-9MhwS4ys8pnwBH7MtnBdLzUv+cb24QC4xbzzQL6A+1MQ4Se2V6oPHEX8TIGIZUPRKi6S1kJPVNzt/Xqqp6/H3Q==", + "requires": { + "color": "^3.1.2", + "detect-libc": "^1.0.3", + "node-addon-api": "^3.0.2", + "npmlog": "^4.1.2", + "prebuild-install": "^5.3.5", + "semver": "^7.3.2", + "simple-get": "^4.0.0", + "tar-fs": "^2.1.0", + "tunnel-agent": "^0.6.0" + } + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4550,6 +4788,51 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.0.tgz", + "integrity": "sha512-ZalZGexYr3TA0SwySsr5HlgOOinS4Jsa8YB2GJ6lUNAazyAu4KG/VmzMTwAt2YVXzzVj8QmefmAonZIK2BSGcQ==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + }, + "dependencies": { + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + } + } + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + } + } + }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -4796,6 +5079,41 @@ "yallist": "^3.0.3" } }, + "tar-fs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.0.tgz", + "integrity": "sha512-9uW5iDvrIMCVpvasdFHW0wJPez0K4JnMZtsuIeDI7HyMGJNxmDZDOCQROr7lXyS+iL/QMpj07qcjGYTSdRFXUg==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.0.0" + } + }, + "tar-stream": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.4.tgz", + "integrity": "sha512-o3pS2zlG4gxr67GmFYBLlq+dM8gyRGUOvsrHclSkvtVtQbjV0s/+ZE8OpICbaj8clrX3tjeHngYGP7rweaBnuw==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -4949,6 +5267,14 @@ "tslib": "^1.8.1" } }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index 258461d..918485e 100644 --- a/package.json +++ b/package.json @@ -16,37 +16,43 @@ "lint-all": "npm run lint && npm run lint-frontend", "lint-all-fix": "npm run lint-fix && npm run lint-frontend-fix", "prettier-check": "prettier src/**/*.ts frontend/src/**/*.ts frontend/src/**/*.tsx --check", - "prettify": "prettier src/**/*.ts frontend/src/**/*.ts frontend/src/**/*.tsx --write" + "prettify": "prettier src/**/*.ts frontend/src/**/*.ts frontend/src/**/*.tsx --write", + "typeorm-dev": "cross-env NODE_ENV=development ts-node -T -r tsconfig-paths/register ./node_modules/typeorm/cli.js", + "typeorm": "ts-node -T -r tsconfig-paths/register ./node_modules/typeorm/cli.js" }, "license": "MIT", "dependencies": { "@koa/cors": "^3.1.0", + "@koa/router": "^9.4.0", "@typescript-eslint/eslint-plugin": "^4.4.0", "@typescript-eslint/parser": "^4.4.0", "bcrypt": "^5.0.0", "chai": "^4.2.0", "concurrently": "^5.3.0", "cross-env": "^7.0.2", + "deasync": "^0.1.20", "eslint": "^7.10.0", "eslint-config-prettier": "^6.12.0", "eslint-import-resolver-typescript": "^2.3.0", "eslint-plugin-import": "^2.22.1", "eslint-plugin-mocha": "^8.0.0", "eslint-plugin-prettier": "^3.1.4", + "hasha": "^5.2.2", "husky": "^4.3.0", "jsonwebtoken": "^8.5.1", "koa": "^2.13.0", "koa-body": "^4.2.0", "koa-jwt": "^4.0.0", "koa-logger": "^3.2.1", - "koa-router": "^9.4.0", "koa-send": "^5.0.1", "koa-sslify": "^4.0.3", "koa-static": "^5.0.0", + "mime-types": "^2.1.27", "mocha": "^8.1.3", "mysql": "^2.18.1", "prettier": "^2.1.2", "prettier-eslint": "^11.0.0", + "sharp": "^0.26.1", "supertest": "^5.0.0", "ts-node": "^9.0.0", "ts-node-dev": "^1.0.0-pre.63", @@ -58,18 +64,22 @@ "@types/bcrypt": "^3.0.0", "@types/chai": "^4.2.13", "@types/concurrently": "^5.2.1", + "@types/deasync": "^0.1.1", "@types/eslint": "^7.2.3", "@types/eslint-plugin-prettier": "^3.1.0", "@types/jsonwebtoken": "^8.5.0", "@types/koa": "^2.11.4", "@types/koa-logger": "^3.1.1", - "@types/koa-router": "^7.4.1", "@types/koa-send": "^4.1.2", "@types/koa-sslify": "^4.0.1", "@types/koa-static": "^4.0.1", "@types/koa__cors": "^3.0.2", + "@types/koa__router": "^8.0.3", + "@types/mime-types": "^2.1.0", "@types/mocha": "^8.0.3", + "@types/mysql": "^2.15.15", "@types/prettier": "^2.1.1", + "@types/sharp": "^0.26.0", "@types/supertest": "^2.0.10" }, "husky": { @@ -77,4 +87,4 @@ "pre-commit": "npm run lint-all && npm run prettier-check" } } -} \ No newline at end of file +} diff --git a/src/app.ts b/src/app.ts index b21e670..2754a90 100644 --- a/src/app.ts +++ b/src/app.ts @@ -8,6 +8,8 @@ import * as logger from "koa-logger"; import * as send from "koa-send"; import sslify, { xForwardedProtoResolver } from "koa-sslify"; import * as serve from "koa-static"; +import * as path from "path"; +import * as fs from "fs"; import { config, EnvType } from "~config"; import { userRouter } from "~routes/users"; @@ -16,9 +18,20 @@ import { photosRouter } from "~routes/photos"; export const app = new Koa(); +const tmpPath = path.join(config.dataDir, "tmp"); + +// Create both data dir if it doesn't exist and temp dir +fs.mkdirSync(tmpPath, { recursive: true }); + app.use(cors()); app.use(logger()); -app.use(bodyParser()); +app.use( + bodyParser({ + multipart: true, + formidable: { uploadDir: tmpPath }, + }), +); + if (config.env === EnvType.production) { app.use(sslify({ resolver: xForwardedProtoResolver })); } @@ -29,6 +42,27 @@ app.use( }), ); +app.use(async (ctx, next) => { + try { + await next(); + } finally { + if (ctx.request.files) { + const filesVals = Object.values(ctx.request.files); + await Promise.all( + filesVals.map(async (f) => { + try { + await fs.promises.unlink(f.path); + } catch (e) { + if (e.code !== "ENOENT") { + throw e; + } + } + }), + ); + } + } +}); + app.use(async (ctx, next) => { try { await next(); diff --git a/src/config/index.ts b/src/config/index.ts index 6c57756..8e2da58 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -11,12 +11,20 @@ export interface IConfig { env: EnvType; port: number; jwtSecret: string; + dataDir: string; dbConnectionOptions: ConnectionOptions | null; } function getJwtSecret(): string { switch (process.env.NODE_ENV) { + case "development": + return "DEVSECRET"; + break; + case "test": + return "TESTSECRET"; + break; case "production": + default: if (process.env.JWT_SECRET === undefined) { console.log("JWT_SECRET is not set"); process.exit(1); @@ -24,15 +32,26 @@ function getJwtSecret(): string { return process.env.JWT_SECRET; } break; + } +} + +function getDataDir(): string { + switch (process.env.NODE_ENV) { case "development": - return "DEVSECRET"; + return "./data_dev"; break; case "test": - return "TESTSECRET"; + return "./data_test"; break; + + case "production": default: - console.log("Unknown NODE_ENV"); - process.exit(1); + if (process.env.DATA_DIR === undefined) { + console.log("DATA_DIR is not set"); + process.exit(1); + } else { + return process.env.DATA_DIR; + } break; } } @@ -41,6 +60,7 @@ const production: IConfig = { env: EnvType.production, port: process.env.PORT ? parseInt(process.env.PORT, 10) : 3000, jwtSecret: getJwtSecret(), + dataDir: getDataDir(), dbConnectionOptions: null, }; diff --git a/src/entity/Photo.ts b/src/entity/Photo.ts index 3016deb..0dc2937 100644 --- a/src/entity/Photo.ts +++ b/src/entity/Photo.ts @@ -1,10 +1,29 @@ +import * as path from "path"; +import * as fs from "fs/promises"; +import * as mime from "mime-types"; +import { constants as fsConstants } from "fs"; + import { + AfterRemove, BaseEntity, + BeforeRemove, Column, Entity, Index, + ManyToOne, PrimaryGeneratedColumn, } from "typeorm"; +import { User } from "./User"; + +export interface IPhotoJSON { + id: number; + user: number; + hash: string; + size: string; + format: string; + createdAt: number; + editedAt: number; +} @Entity() export class Photo extends BaseEntity { @@ -14,4 +33,73 @@ export class Photo extends BaseEntity { @Column({ length: 190 }) @Index() public hash: string; + + @Column({ length: 190 }) + @Index() + public size: string; + + @Column({ length: 190 }) + @Index() + public format: string; + + @Column({ type: "timestamp", default: null }) + public createdAt: Date; + + @Column({ type: "timestamp", default: null }) + public editedAt: Date; + + @ManyToOne(() => User, (user) => user.photos, { eager: true }) + public user: User; + + public getFileName(): string { + return `${this.user.id.toString()}-${this.hash}-${this.size}.${ + mime.extension(this.format) as string + }`; + } + + public getPath(): string { + return path.join(this.user.getDataPath(), this.getFileName()); + } + + @BeforeRemove() + async cleanupFiles(): Promise { + try { + await fs.unlink(this.getPath()); + } catch (e) { + if (e.code !== "ENOENT") { + throw e; + } + } + } + + public async isUploaded(): Promise { + try { + await fs.access(this.getPath(), fsConstants.F_OK); + return true; + } catch (e) { + return false; + } + } + + constructor(user: User, hash: string, size: string, format: string) { + super(); + this.createdAt = new Date(); + this.editedAt = this.createdAt; + this.hash = hash; + this.format = format; + this.size = size; + this.user = user; + } + + public toJSON(): IPhotoJSON { + return { + id: this.id, + user: this.user.id, + hash: this.hash, + size: this.size, + format: this.format, + createdAt: this.createdAt.getTime(), + editedAt: this.editedAt.getTime(), + }; + } } diff --git a/src/entity/User.ts b/src/entity/User.ts index a603692..1b3b0a5 100644 --- a/src/entity/User.ts +++ b/src/entity/User.ts @@ -1,13 +1,21 @@ import * as bcrypt from "bcrypt"; import * as jwt from "jsonwebtoken"; +import * as path from "path"; +import * as fs from "fs/promises"; import { + AfterInsert, + AfterRemove, BaseEntity, + BeforeInsert, + BeforeRemove, Column, Entity, Index, + OneToMany, PrimaryGeneratedColumn, } from "typeorm"; import { config } from "../config"; +import { Photo } from "./Photo"; export type IUserJSON = Pick; @@ -36,6 +44,9 @@ export class User extends BaseEntity { @Column({ length: 190 }) public passwordHash: string; + @OneToMany(() => Photo, (photo) => photo.user) + photos: Promise; + constructor(username: string, email: string) { super(); this.username = username; @@ -50,6 +61,20 @@ export class User extends BaseEntity { this.passwordHash = await bcrypt.hash(password, 10); } + public getDataPath(): string { + return path.join(config.dataDir, this.id.toString()); + } + + @AfterInsert() + async createDataDir(): Promise { + await fs.mkdir(this.getDataPath()); + } + + @BeforeRemove() + async removeDataDir(): Promise { + await fs.rmdir(this.getDataPath(), { recursive: true }); + } + public toJSON(): IUserJSON { const { id, username } = this; return { id, username }; diff --git a/src/routes/dev.ts b/src/routes/dev.ts index 76a955a..69eaeb3 100644 --- a/src/routes/dev.ts +++ b/src/routes/dev.ts @@ -1,9 +1,11 @@ -import * as Router from "koa-router"; +import * as Router from "@koa/router"; +import { Photo } from "~entity/Photo"; import { User } from "~entity/User"; export const devRouter = new Router(); devRouter.post("/dev/clean", async (ctx) => { + await Photo.remove(await Photo.find()); await User.remove(await User.find()); ctx.body = { success: true }; }); diff --git a/src/routes/photos.ts b/src/routes/photos.ts index f38cbb3..1186e99 100644 --- a/src/routes/photos.ts +++ b/src/routes/photos.ts @@ -1,3 +1,234 @@ -import * as Router from "koa-router"; +import * as Router from "@koa/router"; +import { IPhotoJSON, Photo } from "~entity/Photo"; +import { User } from "~entity/User"; +import { IAPIResponse } from "~types"; +import * as fs from "fs/promises"; +import send = require("koa-send"); export const photosRouter = new Router(); + +export interface IPhotosNewPostBody { + hash: string | undefined; + size: string | undefined; + format: string | undefined; +} +export type IPhotosNewRespBody = IAPIResponse; +photosRouter.post("/photos/new", async (ctx) => { + if (!ctx.state.user) { + ctx.throw(401); + } + + const { user } = ctx.state; + const body = ctx.request.body as IPhotosNewPostBody; + const { hash, size, format } = body; + + if (!(hash && size && format)) { + ctx.throw(400); + return; + } + + const photo = new Photo(user.id, hash, size, format); + + try { + await photo.save(); + } catch (e) { + ctx.throw(400); + } + + ctx.body = { + error: false, + data: photo.toJSON(), + } as IPhotosNewRespBody; +}); + +export type IPhotosUploadRespBody = IAPIResponse; +photosRouter.post("/photos/upload/:id", async (ctx) => { + if (!ctx.state.user) { + ctx.throw(401); + } + + const { id } = ctx.params as { + id: number | undefined; + }; + + if (!id) { + ctx.throw(400); + return; + } + + const { user } = ctx.state; + const photo = await Photo.findOne({ id, user }); + if (!photo) { + ctx.throw(404); + return; + } + + if (!ctx.request.files || Object.keys(ctx.request.files).length === 0) { + ctx.throw(400, "No file"); + return; + } + + if (ctx.request.files) { + const files = ctx.request.files; + if (Object.keys(files).length > 1) { + ctx.throw(400, "Too many files"); + return; + } + const file = Object.values(files)[0]; + + try { + // TODO: actually move file if it's on different filesystems + await fs.rename(file.path, photo.getPath()); + } catch (e) { + ctx.throw(500); + } + } + ctx.body = { + error: false, + data: photo.toJSON(), + } as IPhotosUploadRespBody; +}); + +/** +export interface IPhotosByIDPatchBody { +} +export type IPhotosByIDPatchRespBody = IAPIResponse; +photosRouter.patch("/photos/byID/:id", async (ctx) => { + if (!ctx.state.user) { + ctx.throw(401); + return; + } + + const { user } = ctx.state; + const { id } = ctx.params as { + id: number | undefined; + }; + + if (!id) { + ctx.throw(400); + return; + } + + const photo = await Photo.findOne({ id, user }); + + if (!photo) { + ctx.throw(404); + return; + } + + // TODO: Some actual editing + + try { + photo.editedAt = new Date(); + await photo.save(); + } catch (e) { + ctx.throw(400); + } + + ctx.body = { + error: false, + data: photo.toJSON(), + }; +}); +*/ + +export type IPhotosListRespBody = IAPIResponse; +photosRouter.get("/photos/list", async (ctx) => { + if (!ctx.state.user) { + ctx.throw(401); + } + + const { user } = ctx.state; + + const photos = await Photo.find({ user }); + + ctx.body = { + error: false, + data: photos.map((photo) => photo.toJSON()), + } as IPhotosListRespBody; +}); + +export type IPhotosByIDGetRespBody = IAPIResponse; +photosRouter.get("/photos/byID/:id", async (ctx) => { + if (!ctx.state.user) { + ctx.throw(401); + } + + const { id } = ctx.params as { + id: number | undefined; + }; + + if (!id) { + ctx.throw(400); + } + + const { user } = ctx.state; + + const photo = await Photo.findOne({ id, user }); + + if (!photo) { + ctx.throw(404); + return; + } + + ctx.body = { + error: false, + data: photo.toJSON(), + } as IPhotosByIDGetRespBody; +}); + +photosRouter.get("/photos/showByID/:id", async (ctx) => { + if (!ctx.state.user) { + ctx.throw(401); + } + + const { id } = ctx.params as { + id: number | undefined; + }; + + if (!id) { + ctx.throw(400); + } + + const { user } = ctx.state; + + const photo = await Photo.findOne({ id, user }); + + if (!photo) { + ctx.throw(404); + return; + } + + await send(ctx, photo.getPath()); +}); + +export type IPhotosByIDDeleteRespBody = IAPIResponse; +photosRouter.delete("/photos/byID/:id", async (ctx) => { + if (!ctx.state.user) { + ctx.throw(401); + } + + const { id } = ctx.params as { + id: number | undefined; + }; + + if (!id) { + ctx.throw(400); + } + + const { user } = ctx.state; + + const photo = await Photo.findOne({ id, user }); + + if (!photo) { + ctx.throw(404); + return; + } + + await photo.remove(); + + ctx.body = { + error: false, + data: true, + } as IPhotosByIDDeleteRespBody; +}); diff --git a/src/routes/users.ts b/src/routes/users.ts index 415833c..bffb828 100644 --- a/src/routes/users.ts +++ b/src/routes/users.ts @@ -1,8 +1,10 @@ -import * as Router from "koa-router"; -import { IUserJWT, User } from "~entity/User"; +import * as Router from "@koa/router"; +import { IUserAuthJSON, IUserJWT, User } from "~entity/User"; +import { IAPIResponse } from "~types"; export const userRouter = new Router(); +export type IUserGetRespBody = IAPIResponse; userRouter.get("/users/user", async (ctx) => { if (!ctx.state.user) { ctx.throw(401); @@ -17,19 +19,21 @@ userRouter.get("/users/user", async (ctx) => { return; } - ctx.body = { error: false, data: user.toAuthJSON() }; + ctx.body = { error: false, data: user.toAuthJSON() } as IUserGetRespBody; }); +export interface IUserLoginBody { + username: string | undefined; + password: string | undefined; +} +export type IUserLoginRespBody = IAPIResponse; userRouter.post("/users/login", async (ctx) => { const request = ctx.request; if (!request.body) { ctx.throw(400); } - const { username, password } = request.body as { - username: string | undefined; - password: string | undefined; - }; + const { username, password } = request.body as IUserLoginBody; if (!(username && password)) { ctx.throw(400); @@ -42,9 +46,15 @@ userRouter.post("/users/login", async (ctx) => { return; } - ctx.body = { error: false, data: user.toAuthJSON() }; + ctx.body = { error: false, data: user.toAuthJSON() } as IUserLoginRespBody; }); +export interface IUserSignupBody { + username: string | undefined; + password: string | undefined; + email: string | undefined; +} +export type IUserSignupRespBody = IAPIResponse; userRouter.post("/users/signup", async (ctx) => { const request = ctx.request; @@ -52,11 +62,7 @@ userRouter.post("/users/signup", async (ctx) => { ctx.throw(400); } - const { username, password, email } = request.body as { - username: string | undefined; - password: string | undefined; - email: string | undefined; - }; + const { username, password, email } = request.body as IUserSignupBody; if (!(username && password && email)) { ctx.throw(400); @@ -74,9 +80,13 @@ userRouter.post("/users/signup", async (ctx) => { } } - ctx.body = { error: false, data: user.toAuthJSON() }; + ctx.body = { error: false, data: user.toAuthJSON() } as IUserSignupRespBody; }); +export interface IUserEditBody { + password: string | undefined; +} +export type IUserEditRespBody = IAPIResponse; userRouter.post("/users/edit", async (ctx) => { if (!ctx.state.user) { ctx.throw(401); @@ -96,9 +106,7 @@ userRouter.post("/users/edit", async (ctx) => { return; } - const { password } = request.body as { - password: string | undefined; - }; + const { password } = request.body as IUserEditBody; if (!password) { ctx.throw(400); @@ -113,5 +121,5 @@ userRouter.post("/users/edit", async (ctx) => { ctx.throw(400); } - ctx.body = { error: false, data: user.toAuthJSON() }; + ctx.body = { error: false, data: user.toAuthJSON() } as IUserEditRespBody; }); diff --git a/src/tests/integration/photos.test.ts b/src/tests/integration/photos.test.ts new file mode 100644 index 0000000..9aacbb5 --- /dev/null +++ b/src/tests/integration/photos.test.ts @@ -0,0 +1,298 @@ +import { assert, expect } from "chai"; +import { connect } from "config/database"; +import * as request from "supertest"; +import { getConnection } from "typeorm"; +import { app } from "~app"; +import { Photo, IPhotoJSON } from "~entity/Photo"; +import { IPhotosNewPostBody } from "~routes/photos"; +import * as fs from "fs/promises"; +import { constants as fsConstants } from "fs"; + +import { + dogFileSize, + dogFormat, + dogHash, + dogPath, + dogSize, + ISeed, + prepareMetadata, + seedDB, +} from "./util"; +import { sleep } from "deasync"; + +const callback = app.callback(); + +let seed: ISeed; + +describe("photos", function () { + before(async function () { + await connect(); + await prepareMetadata(); + }); + + after(async function () { + await getConnection().close(); + }); + + beforeEach(async function () { + seed = await seedDB(); + }); + + it("should get a photo", async function () { + const response = await request(callback) + .get(`/photos/byID/${seed.dogPhoto.id}`) + .set({ + Authorization: `Bearer ${seed.user2.toJWT()}`, + }) + .expect(200); + + expect(response.body.error).to.be.false; + + const photo = response.body.data as IPhotoJSON; + + const usedPhoto = seed.dogPhoto.toJSON(); + + expect(photo).to.deep.equal(usedPhoto); + }); + + it("should not get a photo without jwt", async function () { + const response = await request(callback) + .get(`/photos/byID/${seed.dogPhoto.id}`) + .set({ + Authorization: `Bearer ${seed.user1.toJWT()}`, + }) + .expect(404); + + expect(response.body.error).to.be.equal("Not Found"); + }); + + it("should show a photo", async function () { + const response = await request(callback) + .get(`/photos/showByID/${seed.dogPhoto.id}`) + .set({ + Authorization: `Bearer ${seed.user2.toJWT()}`, + }) + .expect(200); + expect(parseInt(response.header["content-length"])).to.equal( + dogFileSize, + ); + }); + + it("should not show a photo without jwt", async function () { + const response = await request(callback) + .get(`/photos/byID/${seed.dogPhoto.id}`) + .set({ + Authorization: `Bearer ${seed.user1.toJWT()}`, + }) + .expect(404); + + expect(response.body.error).to.be.equal("Not Found"); + }); + + it("should create, upload and show a photo", async function () { + const response = await request(callback) + .post("/photos/new") + .set({ + Authorization: `Bearer ${seed.user1.toJWT()}`, + "Content-Type": "application/json", + }) + .send({ + hash: dogHash, + size: dogSize, + format: dogFormat, + } as IPhotosNewPostBody) + .expect(200); + + expect(response.body.error).to.be.false; + + const photo = response.body.data as IPhotoJSON; + + expect(photo.hash).to.be.equal(dogHash); + const dbPhoto = await Photo.findOneOrFail({ + id: photo.id, + user: seed.user1.id as any, + }); + expect(dbPhoto.hash).to.be.equal(dogHash); + + await request(callback) + .post(`/photos/upload/${photo.id}`) + .set({ + Authorization: `Bearer ${seed.user1.toJWT()}`, + "Content-Type": "application/json", + }) + .attach("photo", dogPath) + .expect(200); + + const showResp = await request(callback) + .get(`/photos/showByID/${photo.id}`) + .set({ + Authorization: `Bearer ${seed.user1.toJWT()}`, + }) + .expect(200); + + expect(parseInt(showResp.header["content-length"])).to.equal( + dogFileSize, + ); + }); + + it("should create a photo but not upload for other user", async function () { + const response = await request(callback) + .post("/photos/new") + .set({ + Authorization: `Bearer ${seed.user1.toJWT()}`, + "Content-Type": "application/json", + }) + .send({ + hash: dogHash, + size: dogSize, + format: dogFormat, + } as IPhotosNewPostBody) + .expect(200); + + expect(response.body.error).to.be.false; + + const photo = response.body.data as IPhotoJSON; + + expect(photo.hash).to.be.equal(dogHash); + const dbPhoto = await Photo.findOneOrFail({ + id: photo.id, + user: seed.user1.id as any, + }); + expect(dbPhoto.hash).to.be.equal(dogHash); + + await request(callback) + .post(`/photos/upload/${photo.id}`) + .set({ + Authorization: `Bearer ${seed.user2.toJWT()}`, + "Content-Type": "application/json", + }) + .attach("photo", dogPath) + .expect(404); + }); + + it("should create, upload but not show a photo to another user", async function () { + const response = await request(callback) + .post("/photos/new") + .set({ + Authorization: `Bearer ${seed.user1.toJWT()}`, + "Content-Type": "application/json", + }) + .send({ + hash: dogHash, + size: dogSize, + format: dogFormat, + } as IPhotosNewPostBody) + .expect(200); + + expect(response.body.error).to.be.false; + + const photo = response.body.data as IPhotoJSON; + + expect(photo.hash).to.be.equal(dogHash); + const dbPhoto = await Photo.findOneOrFail({ + id: photo.id, + user: seed.user1.id as any, + }); + expect(dbPhoto.hash).to.be.equal(dogHash); + + await request(callback) + .post(`/photos/upload/${photo.id}`) + .set({ + Authorization: `Bearer ${seed.user1.toJWT()}`, + "Content-Type": "application/json", + }) + .attach("photo", dogPath) + .expect(200); + + await request(callback) + .get(`/photos/showByID/${photo.id}`) + .set({ + Authorization: `Bearer ${seed.user2.toJWT()}`, + }) + .expect(404); + }); + + /* + it("should update a photo", async function () { + const response = await request(callback) + .patch(`/photos/byID/${seed.dogPhoto.id}`) + .set({ + Authorization: `Bearer ${seed.user1.toJWT()}`, + "Content-Type": "application/json", + }) + .send({ name: "Test1", content: "Test1" }) + .expect(200); + + expect(response.body.error).to.be.false; + + const photo = response.body.data as IPhotoJSON; + + expect(photo.name).to.be.equal("Test1"); + + const dbPhoto = await Photo.findOne({ + id: seed.dogPhoto.id, + user: seed.user1.id as any, + }); + + expect(dbPhoto.name).to.be.equal("Test1"); + expect(dbPhoto.editedAt.getTime()).to.be.closeTo( + new Date().getTime(), + 2000, + ); + }); + */ + + it("should list photos", async function () { + const response = await request(callback) + .get("/photos/list") + .set({ + Authorization: `Bearer ${seed.user2.toJWT()}`, + }) + .expect(200); + + expect(response.body.error).to.be.false; + + const photos = response.body.data as IPhotoJSON[]; + + const userPhotos = [seed.dogPhoto.toJSON(), seed.catPhoto.toJSON()]; + + expect(photos).to.deep.equal(userPhotos); + }); + + /* + it("should get a shared photo", async function () { + const response = await request(callback) + .get(`/photos/shared/${seed.user1.username}/${seed.catPhoto.id}`) + .expect(200); + + expect(response.body.error).to.be.false; + + const photo = response.body.data as IPhotoJSON; + + const usedPhoto = seed.catPhoto.toJSON(); + + expect(photo).to.deep.equal(usedPhoto); + }); + */ + + it("should delete a photo", async function () { + const photoPath = seed.dogPhoto.getPath(); + const response = await request(callback) + .delete(`/photos/byID/${seed.dogPhoto.id}`) + .set({ + Authorization: `Bearer ${seed.user2.toJWT()}`, + }) + .expect(200); + + expect(response.body.error).to.be.false; + const dbPhoto = await Photo.findOne(seed.dogPhoto.id); + expect(dbPhoto).to.be.undefined; + + try { + await fs.access(photoPath, fsConstants.F_OK); + assert(false); + } catch (e) { + assert(true); + } + }); +}); diff --git a/src/tests/integration/photos/cat.jpg b/src/tests/integration/photos/cat.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fe7cb57cd796c734167cd107bac5660b432b14df GIT binary patch literal 58332 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

QY!-0ot!7aZnp72{}c$60rsEzVIlk$ks zgNy=^=osGJZz~KX7Yrut`d85|l+if@w4o})xyP*-5%)GM@+(zBgN|GT1YYBjhC#LOc;F9J7#kN9`u zh`o2<2g-;kN1A8V+2J0qC(Z}-oYK-xgsBB^*$j17IN#8;9`#N0L~MjZE(*qCDlm)N;b%#^*~npalo}hhpgQt%8R;eBM?1+A z^ya>WV7wa(n#tvGe=X$?_n3z!Q`y?vtt$}l`(BhX4Zh>m z^@uySB9mVw=2|N%3thLMOx>^J&ihb0O4F7u{ov?8(DS=b3*F>VS9L2pu`pjjvj%*0 ztC7vn1CNYj9+B9D0Uj6H^J^XG2!CoE=gaQt0t*KHW--DeG4x4d3fcOcJ#2>6mrbC@X!m z8Lz~K^`!&!bTk}rC&i7Qx9gQqnQul;KJE+4NoY@KSvV!&xbwCTZ2oNQKVC5chwH%m zg`oEb?-%Fp?)@)ci^H8$ChWe6)||`9=qPc0>X2O3MVvt?+)Vd-I=mG{`J&&Z1_3)^ z66F4lMTAYU@s|5M(x|tevQOAk5S-KK<*}ceTy2Lz?>;DP*{28Er%{3}_MNSQwwAU= zn2z+(61+NveKUmxDxK6Fupu5oKKgd-0T18C8kV1`m0cqeNLAO7NF7T_Wv0=8Km$zn zL#t;M_{8{lueh=AM7}D2=HfF%`S6$^dIuoL%!&R6h9WhP`o2wZfs`)54vEVaPBzvj z@63xwbNMr)n;lM=hzC!UxLtJ})-F4TF-eQhKL2#>>x~rcm65u2Q1=Q3x?wq<1}}>) zoM5JuqYSix->sJG-;D=wlSnz4pYr!bOMT!baT>TuP&QZqzs1&~qf2KLtf7-T(wQNa zVY54#&euigF}AdBffv1_HO1mrd~ho zf-MSG2@2?|zw!U7jb{r(F5|Ey*N%W^<1uxPME-Xoo2s;*?^Qxar zSD6}9?*3B8r66mf#DttIQc}!RV!%5RYA_6&z7AvG<>PUeqx#V>+p=+;NB63iT|Q}n z89LY=bCTaW)I4sPI5aZU%^t5j?sOcozI*+bPlcUHJ}^4%`8&*0v>C-oE_@&`tjI4L$f_+g5&~5THmj~wHqdFri8f%wo;lN{DP^k zsLaOSc8prYV7*)f^F+yH_&_8duk@13eIk(=Pq8U`2VLaksdNkV6iic5xDE0FTJ`Fl zgdN8?#O#lWG{m13r^2m0txya6!mDLuL{jl$c#bSd`Y zyA${|#T(mn7OnOxkY|3&2LZ?!90CNgW)*?l4?PZX_ASy`G%bLSy_fATpjNFGWARRi zJF;c_b>io%=7jWkb5>6KE$RGicZW_-)FT{dO-PZb54|eo^iQ>(rW3YMrf*t++bRFR zyuD8&Qj3*X3w0en*3)JAmhCX`%P8$)W~LGdb)1Z*BZ&E~edv?2<}$?wG)MMd})kn1b;dz?^%F7s2P z`zwEbhfWY^cz0|*CKs>kdLwTQtcus`jvh!466|P6sBs&0qd?myP={>%NumZLHV3qU zshg~T!L9xlH2f8Ll4O4#n-WV2jm)@_;@#YPZDa~S&4)|G^xJ|fexx#s1^{?ADWA!j z>lq6jKB&#IjIXW*<@o?K+YsPRT-mlj2VR*Dbm>3>0$R6oM+t!=|1(Ct9P>Ti73$R7Eh(_D74ctEW3p2G|E>mI{SjBZ(Cgdxhd>UaSUttYgd<-P+FmNf{ r`%iuo@6fq@Ka}?ocpriH5qKYg_Yrs>f%g%3AA$D~cxNK8ens}by { + dogHash = await getHash(dogPath); + dogSize = await getSize(dogPath); + dogFileSize = (await fs.stat(dogPath)).size; + catHash = await getHash(catPath); + catSize = await getSize(catPath); + catFileSize = (await fs.stat(catPath)).size; } export async function seedDB(): Promise { - //await Document.remove(await Document.find()); + dogHash = await getHash(dogPath); + dogSize = await getSize(dogPath); + catHash = await getHash(catPath); + catSize = await getSize(catPath); + + await Photo.remove(await Photo.find()); await User.remove(await User.find()); const user1 = new User("User1", "user1@users.com"); @@ -20,11 +49,14 @@ export async function seedDB(): Promise { await user2.setPassword("User2"); await user2.save(); - //const doc1 = new Document(user1, "Doc1", "Doc1", false); - //const doc2p = new Document(user1, "Doc2", "Doc2", true); + const dogPhoto = new Photo(user2, dogHash, dogSize, dogFormat); + const catPhoto = new Photo(user2, catHash, catSize, catFormat); - //await doc1.save(); - //await doc2p.save(); + await fs.copyFile(dogPath, dogPhoto.getPath()); + await fs.copyFile(catPath, catPhoto.getPath()); - return { user1, user2 }; // doc1, doc2p }; + await dogPhoto.save(); + await catPhoto.save(); + + return { user1, user2, dogPhoto, catPhoto }; } diff --git a/src/types.ts b/src/types.ts index 88b4e40..d33e7c8 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,4 +1,12 @@ -export interface IAPIResponse { - data: T | null; - error: string | null; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +interface IAPIErrorResponse { + data: null; + error: string; } + +interface IAPISuccessResponse { + error: false; + data: T; +} + +export type IAPIResponse = IAPIErrorResponse | IAPISuccessResponse; diff --git a/src/util.ts b/src/util.ts new file mode 100644 index 0000000..c71ff87 --- /dev/null +++ b/src/util.ts @@ -0,0 +1,24 @@ +import deasync = require("deasync"); +import { fromFile } from "hasha"; +import sharp = require("sharp"); + +export async function getHash(file: string): Promise { + return await fromFile(file, { + algorithm: "md5", + }); +} + +export async function getSize(file: string): Promise { + const metadata = await sharp(file).metadata(); + if (!(metadata.width && metadata.height)) { + throw new Error( + `The ${file} doesn't have width and height... how did we get there?`, + ); + } + return `${metadata.width}x${metadata.height}`; +} + +// eslint-disable-next-line @typescript-eslint/no-misused-promises +export const getHashSync: (file: string) => string = deasync(getHash); +// eslint-disable-next-line @typescript-eslint/no-misused-promises +export const getSizeSync: (file: string) => string = deasync(getSize);