diff --git a/.travis.yml b/.travis.yml index 5bdf82b..6f83e19 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: node_js node_js : - "node" before_script: -- psql -c 'CREATE DATABASE toolshare;' -U postgres +- psql -c 'CREATE DATABASE toolshare_test;' -U postgres - psql -c "CREATE USER sunuwars WITH PASSWORD 'sunuwars123';" -U postgres -- psql -c 'ALTER DATABASE toolshare OWNER TO sunuwars;' -U postgres +- psql -c 'ALTER DATABASE toolshare_test OWNER TO sunuwars;' -U postgres after_success: npm run coverage diff --git a/package-lock.json b/package-lock.json index 413cc11..106fdb6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -987,6 +987,436 @@ } } }, + "bcrypt": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-3.0.0.tgz", + "integrity": "sha512-gjicxsD4e5U3nH0EqiEb5y+fKpsZ7F52wcnmNfu45nxnolWVAYh7NgbdfilY+5x1v6cLspxmzz4hf+ju2pFxhA==", + "requires": { + "nan": "2.10.0", + "node-pre-gyp": "0.10.2" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.5" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "requires": { + "minipass": "2.3.3" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.3" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "iconv-lite": { + "version": "0.4.23", + "bundled": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "minipass": { + "version": "2.3.3", + "bundled": true, + "requires": { + "safe-buffer": "5.1.2", + "yallist": "3.0.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "requires": { + "minipass": "2.3.3" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true + }, + "needle": { + "version": "2.2.1", + "bundled": true, + "requires": { + "debug": "2.6.9", + "iconv-lite": "0.4.23", + "sax": "1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.2", + "bundled": true, + "requires": { + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.1", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.8", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "requires": { + "are-we-there-yet": "1.1.5", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "requires": { + "deep-extend": "0.6.0", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true + } + } + }, + "readable-stream": { + "version": "2.3.5", + "bundled": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true + }, + "sax": { + "version": "1.2.4", + "bundled": true + }, + "semver": { + "version": "5.5.0", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "bundled": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + }, + "tar": { + "version": "4.4.4", + "bundled": true, + "requires": { + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.3.3", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.2", + "yallist": "3.0.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + } + } + }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -3112,6 +3542,15 @@ "write": "0.2.1" } }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "1.1.4" + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -3209,8 +3648,8 @@ "dev": true, "optional": true, "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" + "delegates": "1.0.0", + "readable-stream": "2.3.6" } }, "balanced-match": { @@ -3287,7 +3726,7 @@ "dev": true, "optional": true, "requires": { - "minipass": "^2.2.1" + "minipass": "2.2.4" } }, "fs.realpath": { @@ -3302,14 +3741,14 @@ "dev": true, "optional": true, "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" } }, "glob": { @@ -3318,12 +3757,12 @@ "dev": true, "optional": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, "has-unicode": { @@ -3338,7 +3777,7 @@ "dev": true, "optional": true, "requires": { - "safer-buffer": "^2.1.0" + "safer-buffer": "2.1.2" } }, "ignore-walk": { @@ -3347,7 +3786,7 @@ "dev": true, "optional": true, "requires": { - "minimatch": "^3.0.4" + "minimatch": "3.0.4" } }, "inflight": { @@ -3356,8 +3795,8 @@ "dev": true, "optional": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "once": "1.4.0", + "wrappy": "1.0.2" } }, "inherits": { @@ -3376,7 +3815,7 @@ "bundled": true, "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "number-is-nan": "1.0.1" } }, "isarray": { @@ -3403,8 +3842,8 @@ "bundled": true, "dev": true, "requires": { - "safe-buffer": "^5.1.1", - "yallist": "^3.0.0" + "safe-buffer": "5.1.1", + "yallist": "3.0.2" } }, "minizlib": { @@ -3413,7 +3852,7 @@ "dev": true, "optional": true, "requires": { - "minipass": "^2.2.1" + "minipass": "2.2.4" } }, "mkdirp": { @@ -3436,9 +3875,9 @@ "dev": true, "optional": true, "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" + "debug": "2.6.9", + "iconv-lite": "0.4.21", + "sax": "1.2.4" } }, "node-pre-gyp": { @@ -3447,16 +3886,16 @@ "dev": true, "optional": true, "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.1.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.0", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.7", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.1" } }, "nopt": { @@ -3465,8 +3904,8 @@ "dev": true, "optional": true, "requires": { - "abbrev": "1", - "osenv": "^0.1.4" + "abbrev": "1.1.1", + "osenv": "0.1.5" } }, "npm-bundled": { @@ -3481,8 +3920,8 @@ "dev": true, "optional": true, "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" } }, "npmlog": { @@ -3491,10 +3930,10 @@ "dev": true, "optional": true, "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" } }, "number-is-nan": { @@ -3513,7 +3952,7 @@ "bundled": true, "dev": true, "requires": { - "wrappy": "1" + "wrappy": "1.0.2" } }, "os-homedir": { @@ -3534,8 +3973,8 @@ "dev": true, "optional": true, "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" } }, "path-is-absolute": { @@ -3556,10 +3995,10 @@ "dev": true, "optional": true, "requires": { - "deep-extend": "^0.5.1", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" }, "dependencies": { "minimist": { @@ -3576,13 +4015,13 @@ "dev": true, "optional": true, "requires": { - "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" + "core-util-is": "1.0.2", + "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.2" } }, "rimraf": { @@ -3591,7 +4030,7 @@ "dev": true, "optional": true, "requires": { - "glob": "^7.0.5" + "glob": "7.1.2" } }, "safe-buffer": { @@ -3634,9 +4073,9 @@ "bundled": true, "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } }, "string_decoder": { @@ -3645,7 +4084,7 @@ "dev": true, "optional": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.1" } }, "strip-ansi": { @@ -3653,7 +4092,7 @@ "bundled": true, "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "strip-json-comments": { @@ -3668,13 +4107,13 @@ "dev": true, "optional": true, "requires": { - "chownr": "^1.0.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", - "yallist": "^3.0.2" + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.2.4", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.1", + "yallist": "3.0.2" } }, "util-deprecate": { @@ -3689,7 +4128,7 @@ "dev": true, "optional": true, "requires": { - "string-width": "^1.0.2" + "string-width": "1.0.2" } }, "wrappy": { @@ -5966,9 +6405,7 @@ "nan": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", - "dev": true, - "optional": true + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" }, "nanomatch": { "version": "1.2.13", @@ -8725,9 +9162,9 @@ "integrity": "sha1-QlfCVt8/sLRR1q/6qwIYhBJpgdw=", "dev": true, "requires": { - "is-finite": "^1.0.1", - "parse-ms": "^1.0.0", - "plur": "^1.0.0" + "is-finite": "1.0.2", + "parse-ms": "1.0.1", + "plur": "1.0.0" } }, "private": { @@ -9119,6 +9556,15 @@ "signal-exit": "3.0.2" } }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "dev": true, + "requires": { + "through": "2.3.8" + } + }, "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", @@ -9899,6 +10345,17 @@ "regexp.prototype.flags": "1.2.0" } }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.12.0", + "function-bind": "1.1.1" + } + }, "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", @@ -10066,7 +10523,7 @@ "integrity": "sha1-xDlc5oOrzSVLwo/h2rtuXCfc/64=", "dev": true, "requires": { - "through": "2" + "through": "2.3.8" } } } @@ -10077,14 +10534,14 @@ "integrity": "sha512-zMDVJiE5I6Y4XGjlueGXJIX2YIkbDN44broZlnypT38Hj/czfOXrszHNNJBF/DXR8n+x6gbfSx68x04kIEHdrw==", "dev": true, "requires": { - "chalk": "^1.0.0", - "duplexer": "^0.1.1", - "figures": "^1.4.0", - "lodash": "^4.17.10", - "pretty-ms": "^2.1.0", - "repeat-string": "^1.5.2", - "tap-out": "^2.1.0", - "through2": "^2.0.0" + "chalk": "1.1.3", + "duplexer": "0.1.1", + "figures": "1.7.0", + "lodash": "4.17.10", + "pretty-ms": "2.1.0", + "repeat-string": "1.6.1", + "tap-out": "2.1.0", + "through2": "2.0.3" }, "dependencies": { "figures": { @@ -10093,8 +10550,8 @@ "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "dev": true, "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" } } } @@ -10105,19 +10562,19 @@ "integrity": "sha512-6fKIXknLpoe/Jp4rzHKFPpJUHDHDqn8jus99IfPnHIjyz78HYlefTGD3b5EkbQzuLfaEvmfPK3IolLgq2xT3kw==", "dev": true, "requires": { - "deep-equal": "~1.0.1", - "defined": "~1.0.0", - "for-each": "~0.3.3", - "function-bind": "~1.1.1", - "glob": "~7.1.2", - "has": "~1.0.3", - "inherits": "~2.0.3", - "minimist": "~1.2.0", - "object-inspect": "~1.6.0", - "resolve": "~1.7.1", - "resumer": "~0.0.0", - "string.prototype.trim": "~1.1.2", - "through": "~2.3.8" + "deep-equal": "1.0.1", + "defined": "1.0.0", + "for-each": "0.3.3", + "function-bind": "1.1.1", + "glob": "7.1.2", + "has": "1.0.3", + "inherits": "2.0.3", + "minimist": "1.2.0", + "object-inspect": "1.6.0", + "resolve": "1.7.1", + "resumer": "0.0.0", + "string.prototype.trim": "1.1.2", + "through": "2.3.8" } }, "term-size": { @@ -10193,8 +10650,8 @@ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" + "readable-stream": "2.2.9", + "xtend": "4.0.1" } }, "timed-out": { diff --git a/package.json b/package.json index 6722f79..870867e 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "", "main": "index.js", "dependencies": { + "bcrypt": "^3.0.0", "env2": "^2.2.2", "eslint": "^5.3.0", "eslint-config-node": "^3.0.0", @@ -23,7 +24,7 @@ "tape": "^4.9.1" }, "scripts": { - "test": "tape ./test/post-data.test.js", + "test": "NODE_ENV=test tape ./test/*.test.js | tap-spec", "dev": "nodemon src/server.js", "start": "node src/server.js" }, diff --git a/public/index.html b/public/index.html index af2bfd1..a9898ab 100644 --- a/public/index.html +++ b/public/index.html @@ -12,6 +12,9 @@ +

Michael's List

@@ -21,16 +24,23 @@

Lend and borrow items with your FAC friends

Would you like to borrow anything?

- +
+ + +
+ + +
- +
@@ -46,6 +56,7 @@

Would you like to lend anything?

+

Item to borrow

+
+

Sign up form

+
+ + + + + + + + + + + + +
+ +
- \ No newline at end of file + diff --git a/public/script.js b/public/script.js index 648712e..53dc1c6 100644 --- a/public/script.js +++ b/public/script.js @@ -11,6 +11,7 @@ var submitItemBtn = document.getElementById("submit-item"); var allItemsBtn = document.getElementById("all-items-btn"); var nameCol = document.getElementById("name-column"); var descCol = document.getElementById("desc-column"); +var borrowH3 = document.getElementById("borrow-item-title"); function request(url, method, cb) { var xhr = new XMLHttpRequest(); @@ -89,9 +90,11 @@ requestBtn.addEventListener("click", function(e) { xhrPost.send(JSON.stringify(postData)); }); -function borrow(id) { +function borrow(id, name) { reqForm.classList.remove("hidden"); itemIdInput.value = id; + console.log("name: ", name); + borrowH3.innerText = "Borrow " + name.toLowerCase(); } searchBtn.addEventListener("click", function(e) { @@ -128,32 +131,50 @@ function updateDom(err, data) { //add headers var nameHeader = document.createElement("th"); + var availHeader = document.createElement("th"); var descHeader = document.createElement("th"); var buttonHeader = document.createElement("th"); var row = document.createElement("tr"); - nameHeader.textContent = "Item Name"; - descHeader.textContent = "Item Description"; + nameHeader.className = "itm-name-col"; + availHeader.className = "itm-avail-col"; + descHeader.className = "itm-descr-col"; + buttonHeader.className = "itm-borrow-col"; + + nameHeader.textContent = "Item"; + availHeader.textContent = "Available"; + descHeader.textContent = "Description"; buttonHeader.textContent = "Borrow"; row.appendChild(nameHeader); + row.appendChild(availHeader); row.appendChild(descHeader); row.appendChild(buttonHeader); table.appendChild(row); if (items.length > 0) { items.forEach(function(item) { + console.log(item); // adding our item names var row = document.createElement("tr"); var name = document.createElement("td"); + name.className = "itm-name-col"; + var available = document.createElement("td"); + available.className = "itm-avail-col"; + available.innerHTML = item.on_loan; var loanBtn = document.createElement("button"); loanBtn.textContent = "borrow"; + loanBtn.className = "itm-borrow-col"; loanBtn.setAttribute("id", item.id); - loanBtn.setAttribute("onclick", "borrow(this.id)"); + loanBtn.setAttribute( + "onclick", + "borrow(this.id, " + "'" + item.name + "')" + ); name.innerHTML = item.name; row.appendChild(name); - + row.appendChild(available); // adding our item descriptions var description = document.createElement("td"); + description.className = "itm-descr-col"; description.innerHTML = item.description; row.appendChild(description); row.appendChild(loanBtn); @@ -168,4 +189,122 @@ function updateDom(err, data) { } } -request("/testing", "GET", updateDom); +var regButton = document.getElementById("submit-reg"); +var error = document.querySelector(".error"); +var regForm = document.getElementById("reg-form"); +var regFormInput = document.querySelectorAll("reg-form-input"); +var regName = document.getElementById("reg-name"); +var regEmail = document.getElementById("reg-email"); +var password = document.getElementById("reg-password"); +var confirmPassword = document.getElementById("reg-confirm-password"); + +regButton.addEventListener( + "click", + function(e) { + + error.classList.add("passive"); + + // checks that a name has been entered + if (regName.validity.valueMissing) { + error.innerHTML = "Please enter a name"; + error.className = "error"; + regName.classList.add("incorrect-field"); + return; + } + + // checks that email is valid + if (regEmail.validity.typeMismatch || regEmail.validity.valueMissing) { + error.innerHTML = "Please enter a valid email address"; + error.className = "error"; + regEmail.classList.add("incorrect-field"); + return; + } + + // checks that anything has been entered into password fields + if (password.validity.valueMissing || confirmPassword.validity.valueMissing) { + error.innerHTML = "Please enter a password and confirm your password"; + error.className = "error"; + password.classList.add("incorrect-field"); + confirmPassword.classList.add("incorrect-field"); + return; + } + + // checks that email is valid + if (regEmail.validity.typeMismatch || regEmail.validity.valueMissing) { + console.log("reached"); + error.innerHTML = "Please enter a valid email address"; + error.className = "error"; + regEmail.classList.add("incorrect-field"); + return; + } + + // checks that anything has been entered into password fields + if (password.validity.valueMissing || confirmPassword.validity.valueMissing) { + error.innerHTML = "Please enter a password and confirm your password"; + error.className = "error"; + password.classList.add("incorrect-field"); + confirmPassword.classList.add("incorrect-field"); + return; + } + + // check that the passwords fit the required pattern + if ( + password.validity.patternMismatch || + confirmPassword.validity.patternMisMatch + ) { + error.innerHTML = + "Password must contain at least eight characters, including one letter and one number"; + error.className = "error"; + password.classList.add("incorrect-field"); + confirmPassword.classList.add("incorrect-field"); + return; + } + + if (password.value != confirmPassword.value) { + error.innerHTML = "Passwords do not match"; + error.className = "error"; + password.classList.add("incorrect-field"); + confirmPassword.classList.add("incorrect-field"); + return; + } else { + error.innerHTML = ""; + error.classList.add("passive"); + } +}); + +regForm.addEventListener( + "input", + function(e) { + for (let i = 0; i < regForm.length; i++) { + if (regForm[i].validity.valid) { + regForm[i].classList.remove("incorrect-field"); + } + } + } +); + +regEmail.addEventListener("focusout", function(e) { + if (!regEmail.validity.valid) { + regEmail.classList.add("invalid-input"); + } else if (regEmail.validity.valid) { + regEmail.classList.remove("invalid-input"); + } +}); + +password.addEventListener("focusout", function(e) { + if (password.validity.patternMismatch) { + password.classList.add("invalid-input"); + } else if (password.validity.valid) { + password.classList.remove("invalid-input"); + } +}); + +confirmPassword.addEventListener("focusout", function(e) { + if (confirmPassword.validity.patternMismatch) { + confirmPassword.classList.add("invalid-input"); + } else if (confirmPassword.validity.valid) { + confirmPassword.classList.remove("invalid-input"); + } +}); + +request("/populate-all", "GET", updateDom); diff --git a/public/style.css b/public/style.css index 5ead2c6..02e0652 100644 --- a/public/style.css +++ b/public/style.css @@ -148,6 +148,19 @@ body { display: none; } +nav { + position: fixed; + height: 48px; + background-color: hsl(10, 100%, 80%); + width: 100vw; + display: flex; + justify-content: flex-end; + align-items: center; + padding: 8px; + padding-right: 128px; + font-family: "Raleway", sans-serif; +} + main { display: flex; flex-direction: column; @@ -157,6 +170,7 @@ main { /* height: 100vh; */ margin: 0 128px 0 128px; padding: 0; + padding-top: 48px; } header { @@ -190,6 +204,10 @@ h3 { color: hsl(165, 100%, 15%); } +header > h3 { + color: green; +} + .content-container { width: 100%; } @@ -255,13 +273,13 @@ h3 { #items-table > tr > td { display: flex; justify-content: center; - width: 33%; + /* width: 33%; */ } #items-table > tr > th { display: flex; justify-content: center; - width: 33%; + /* width: 33%; */ font-size: 1.5rem; font-weight: 700; } @@ -269,7 +287,7 @@ h3 { #items-table > tr > button { display: flex; justify-content: center; - width: 33%; + /* width: 33%; */ font-size: 1rem; padding: 8px 16px 8px 16px; background: hsl(10, 100%, 80%); @@ -296,14 +314,16 @@ h3 { color: hsl(164, 50%, 90%); } -#submit-item-form { +#submit-item-form, +#reg-form { display: flex; flex-direction: column; justify-content: center; align-items: space-between; } -#submit-item-form > input { +#submit-item-form > input, +.reg-form-input { font-size: 1rem; padding: 8px; border: hsl(10, 100%, 80%) 2px solid; @@ -320,7 +340,8 @@ h3 { width: 60%; } -#submit-item-form > button { +#submit-item-form > button, +#reg-form > button { display: flex; justify-content: center; font-size: 1rem; @@ -375,3 +396,109 @@ h3 { color: white; border: solid 6px hsl(165, 50%, 70%); } + +#checkbox, +#srch-input-div { + display: flex; + flex-direction: column; +} +#search-form { + /* display:flex; + flex-direction: row; + flex-wrap: wrap; + align-content: center; */ + height: 39px; + /* very hacky solution. need to revisit */ +} + +#avail-label { + font-size: 1rem; + line-height: 1.4rem; +} + +/* button { + display: flex; + justify-content: center; + font-size: 1rem; + padding: 8px 16px 8px 16px; + background: hsl(10, 100%, 80%); + border: hsl(10, 100%, 80%) 2px solid; + color: white; + cursor: pointer; + margin: auto; + width: 60%; +} */ + +#srch-input-div > input { + font-size: 1rem; + padding: 8px; + border: hsl(10, 100%, 80%) 2px solid; + margin: 0; + margin-right: 16px; + color: hsl(165, 100%, 15%); +} + +.itm-name-col { + width: 25%; +} +.itm-avail-col { + width: 10%; +} +.itm-descr-col { + width: 50%; +} +.itm-borrow-col { + width: 15%; +} + +h3 { + color: hsl(164, 50%, 90%); +} + +/* INPUT VALIDATION */ + +/* input[type="email"]:invalid { + border: 2px dashed red; + outline: none; + background-color: lightpink; +} */ + +/* input[type="email"]:placeholder-shown { + border: hsl(10, 100%, 80%) 2px solid; + background-color: white; +} */ + +.invalid-input { + border: 2px dashed red; + outline: none; + background-color: lightpink; +} + +.error { + width: 100%; + font-size: 80%; + color: red; + box-sizing: border-box; + display: flex; + text-align: center; + justify-content: center; + padding-bottom: 24px; +} + +.passive { + position: absolute; +} + +.incorrect-field { + border: solid 2px red; + background-color: lightpink; +} + +.disclaimer { + font-size: 0.5rem; +} + +#reg-form > span { + width: 0; +} + diff --git a/src/database/db_build.sql b/src/database/db_build.sql index 2f95d81..1c5b435 100644 --- a/src/database/db_build.sql +++ b/src/database/db_build.sql @@ -1,17 +1,18 @@ BEGIN; -DROP TABLE IF EXISTS users, items, loans CASCADE; +DROP TABLE IF EXISTS users, items, loans, active_sessions CASCADE; CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(80) NOT NULL, - email VARCHAR(80) NOT NULL, - fav_colour VARCHAR(6) + email VARCHAR(80) UNIQUE NOT NULL, + fav_colour VARCHAR(6), + password_hash VARCHAR(60) NOT NULL ); -INSERT INTO users (name, email, fav_colour) VALUES - ('Sangita Sunuwar', 'sangita@gmail.com', '800080'), - ('Dominic Coelho', 'domwork@live.com', '91a3b0'); +INSERT INTO users (name, email, fav_colour, password_hash) VALUES + ('Sangita Sunuwar', 'sangita@gmail.com', '800080', '$2b$12$tAq9f9q4sVQhZ7JwVarYtuh7dZNOzGz.EN/VHiHDo7A2Vm/yHy3/e'), + ('Dominic Coelho', 'domwork@live.com', '91a3b0', '$2b$12$9KMMDuR2Le5n1.tl1LYqOuVCRXjwpIRfj0RafQa/mppqgNTD7.P8u'); CREATE TABLE items ( id SERIAL PRIMARY KEY, @@ -23,8 +24,8 @@ CREATE TABLE items ( INSERT INTO items (name, description, lender_id, on_loan) VALUES ('Knife', 'Sharp blade!', 2, TRUE), - ('Lawnmower', 'Sharp blades!', 1, TRUE), - ('Shovel', 'Good for hiding bodies', 1, FALSE), + ('Lawnmower', 'Sharp blades!', 1, TRUE), + ('Shovel', 'Good for hiding bodies', 1, FALSE), ('Cake', 'Eat it soon', 2, TRUE), ('White chocolate', 'Disgusting', 2, FALSE); @@ -39,12 +40,21 @@ CREATE TABLE loans ( INSERT INTO loans (item_id, borrowers_id) VALUES (1, 1); -INSERT INTO loans (item_id, borrowers_id, issue_date) VALUES +INSERT INTO loans (item_id, borrowers_id, issue_date) VALUES (2, 2, '2018-08-07'); -INSERT INTO loans (item_id, borrowers_id, issue_date, return_date) VALUES - (3, 2, '2018-08-05', '2018-08-08'), - (4, 1, '2018-08-05', '2018-08-06'), +INSERT INTO loans (item_id, borrowers_id, issue_date, return_date) VALUES + (3, 2, '2018-08-05', '2018-08-08'), + (4, 1, '2018-08-05', '2018-08-06'), (4, 1, '2018-08-07', NULL); +CREATE TABLE active_sessions ( + id SERIAL PRIMARY KEY, + session_id VARCHAR(100) NOT NULL UNIQUE, + email VARCHAR(80) REFERENCES users(email) NOT NULL, + creation_date DATE NOT NULL DEFAULT CURRENT_DATE +); + +-- NEED TO INSERT DUMMY DATA INTO sessions TABLE + COMMIT; diff --git a/src/database/db_connection.js b/src/database/db_connection.js index 6a03ff3..5d08a26 100644 --- a/src/database/db_connection.js +++ b/src/database/db_connection.js @@ -1,29 +1,26 @@ +const { Pool } = require("pg"); +const url = require("url"); +require("env2")("./config.env"); -const {Pool} = require('pg'); -const url = require('url'); -require('env2')('./config.env'); - - -let DB_URL = process.env.DB_URL; -if (process.env.NODE_ENV === 'test') { +let DB_URL = process.env.DATABASE_URL; +if (process.env.NODE_ENV === "test") { DB_URL = process.env.TEST_DB_URL; } -if (!DB_URL) throw new Error('Environment variable DB_URL must be set'); +if (!DB_URL) throw new Error("Environment variable DB_URL must be set"); const params = url.parse(DB_URL); -const [username, password] = params.auth.split(':'); +const [username, password] = params.auth.split(":"); const options = { host: params.hostname, port: params.port, - database: params.pathname.split('/')[1], + database: params.pathname.split("/")[1], max: process.env.DB_MAX_CONNECTIONS || 2, user: username, - password, + password }; -options.ssl = options.host !== 'localhost'; - +options.ssl = options.host !== "localhost"; -module.exports = new Pool(options); \ No newline at end of file +module.exports = new Pool(options); diff --git a/src/handlers.js b/src/handlers.js index 0941610..e1a3a5d 100644 --- a/src/handlers.js +++ b/src/handlers.js @@ -1,10 +1,11 @@ -/* eslint-disable */ - const fs = require("fs"); const path = require("path"); -const {postData, insertData} = require("./queries/postData"); +const { postData, checkUser, insertData } = require("./queries/postData"); const getData = require("./queries/getData"); const runDbBuild = require("./database/db_build"); +const passwords = require("./passwords"); +const querystring = require("querystring"); +const crypto = require("crypto"); const buildPath = function(myPath) { return path.join(__dirname, "..", "public", myPath); @@ -21,7 +22,36 @@ const contentType = { ".gif": "image/gif" }; +const sessionIDGen = function(length = 24){ + return new Promise((resolve, reject) => { + crypto.randomBytes(48, (err, buffer) => { + if (err) { + reject(err); + } else { + resolve (buffer.toString("hex")) + } + }) + }) +} + const handlers = { + collectData(req, cb) { + let data = ""; + console.log("req: ", req); + req + .on("data", chunk => { + console.log("chunk: ", chunk); + data += chunk; + }) + .on("error", err => { + cb(err); + }) + .on("end", () => { + cb(null, querystring.parse(data)) + // cb(null, JSON.parse(data)); + }); + }, + home(req, res) { fs.readFile(buildPath("index.html"), (err, file) => { if (err) { @@ -50,6 +80,100 @@ const handlers = { }); }, + register(req, res) { + if (req.method === "POST") { + handlers.collectData(req, (err, data) => { + console.log("collected data"); + if (err) { + res.writeHead(500, { "Content-Type": "text/html" }); + res.end("

Server Error

"); + } else if ( + !data["reg-name"] || + !data["reg-email"] || + !data["reg-password"] || + !data["fav-colour"] + ) { + console.log("data missing"); + console.log("data: ", data); + res.writeHead(500, { "Content-Type": "text/html" }); + res.end("

Server Error

"); + } else { + console.log(data); + // sanitise data + const name = data["reg-name"].replace(/[^a-z0-9_\- ]/gi, ""); + const email = data["reg-email"].replace(/[^a-z0-9._\-@+]/gi, ""); + const password = data["reg-password"]; + const favColour = data["fav-colour"] + .replace(/[^a-z0-9]/gi, "") + .substring(0, 6); + // check email doesn't exist + checkUser(email, (err, result) => { + if (err) { + res.writeHead(500, { "Content-Type": "text/html" }); + res.end("

Server Error

"); + } else if (result) { + res.writeHead(200, { "Content-Type": "text/html" }); + res.end("

Email already exists

"); + } else { + passwords.hashPassword(password, (err, hashedPassword) => { + if (err) { + res.writeHead(500, { "Content-Type": "text/html" }); + res.end("

Hashed pw error

"); + } + passwords.storePassword( + name, + email, + favColour, + hashedPassword, + (err, result) => { + if (err) { + res.writeHead(500, { "Content-Type": "text/html" }); + res.end("

Server Error in storepassword func

"); + } + + // Create session token! + sessionIDGen() + .then( + sessionID => { + passwords.storeSession( + sessionID, + email, + (err, result, sssionID) => { + console.log("Store Session func reached") + if (err) { + res.writeHead(500, { "Content-Type": "text/html" }); + res.end("

Server Error in storeSession func

"); + } else { + res.writeHead(200, { "Content-Type": "text/html", "Set-Cookie": `session_id=${sssionID}; HttpOnly; Max-Age=43200` }) + res.end("

User added to database :)

") + } + } + )} + ) + // .then( + // (sessID) => { + // res.writeHead(200, { "Content-Type": "text/html", "Set-Cookie": `session_id='${sessID}'` }) + // res.end("

User added to database :)

") + // } + // ) + // .then() + // create cookie + // store session data + // all that jazz + + + } + ); + }); + } + }); + // hash password + // store user + } + }); + } + }, + search(req, res, endpoint) { const qry = decodeURIComponent(endpoint.split("?q=")[1]) .replace(/[^A-Za-z0-9 ]/, "") @@ -62,35 +186,29 @@ const handlers = { } else { res.writeHead(200, "Content-type: application/json"); res.end(JSON.stringify(result)); - } + } }); }, requestItem(req, res) { if (req.method === "POST") { - let data = ""; - req - .on("data", chunk => { - data += chunk; - }) - .on("end", () => { - const parsedData = JSON.parse(data); - console.log(parsedData.name, parsedData.email, parsedData.item); - postData( - parsedData.name, - parsedData.email, - Number(parsedData.item), - err => { - if (err) { - res.writeHead(500, { "Content-Type": "text/html" }); - res.end("

Server Error

"); - console.log("postdata error"); - } else { - res.writeHead(302, { Location: "/success" }); - res.end(); - } + handlers.collectData(req, (err, data) => { + const parsedData = JSON.parse(data); + postData( + parsedData.name, + parsedData.email, + Number(parsedData.item), + err => { + if (err) { + res.writeHead(500, { "Content-Type": "text/html" }); + res.end("

Server Error

"); + console.log("postdata error"); + } else { + res.writeHead(302, { Location: "/success" }); + res.end(); } - ); - }); + } + ); + }); } }, success(req, res) { @@ -108,57 +226,55 @@ const handlers = { addItem(req, res) { // SQL query: Add user // SQL query: Add item from that user + console.log("addItem reached"); if (req.method === "POST") { let data = ""; - req.on("data", chunk => { - data += chunk; - }) - .on("end", () => { - const parsedData = JSON.parse(data); - console.log("PARSED DATA: ", parsedData); - // Previously used parsedData.data.name etc below - insertData( - parsedData.name, - parsedData.email, - parsedData.itemName, - parsedData.itemDesc, - parsedData.favColour, - err => { - if (err) { - res.writeHead(500, { "Content-Type": "text/html" }); - res.end("

Server Error

"); - console.log("insertdata error"); - } else { - //need to change location? - res.writeHead(302, { Location: "/success" }); - res.end(); + req + .on("data", chunk => { + data += chunk; + }) + .on("end", () => { + const parsedData = JSON.parse(data); + console.log("got data"); + // Previously used parsedData.data.name etc below + insertData( + parsedData.name, + parsedData.email, + parsedData.itemName, + parsedData.itemDesc, + parsedData.favColour, + err => { + if (err) { + res.writeHead(500, { "Content-Type": "text/html" }); + res.end("

Server Error

"); + console.log("insertdata error"); + } else { + //need to change location? + console.log("else, should be 302"); + res.writeHead(302, { Location: "/success" }); + res.end(); + } } - } - ) - }) + ); + }); } - - }, - testData: function(req, response) { + testData(req, response) { // runDbBuild((err, res) => { // if (err) { // response.writeHead(500, "Content-Type:text/html"); // response.end("

Sorry, there was a problem getting the users

"); // console.log(err); // } else { - getData("", (err, res) => { - if (err) { - response.writeHead(500, "Content-Type:text/html"); - response.end( - "

Sorry, there was a problem getting the users

" - ); - console.log(err); - } - response.writeHead(200, { "Content-Type": "application/json" }); - response.end(JSON.stringify(res)); - }); + getData("", (err, res) => { + if (err) { + response.writeHead(500, "Content-Type:text/html"); + response.end("

Sorry, there was a problem getting the users

"); + } + response.writeHead(200, { "Content-Type": "application/json" }); + response.end(JSON.stringify(res)); + }); // } // }); } diff --git a/src/passwords.js b/src/passwords.js new file mode 100644 index 0000000..cf97225 --- /dev/null +++ b/src/passwords.js @@ -0,0 +1,47 @@ +const bcrypt = require("bcrypt"); +const dbConnection = require("./database/db_connection"); +const SALT_ROUNDS = 12; + +const passwords = { + // takes in plaintext password and salt, hashes it, stores it in database + // hash plaintext password + hashPassword: (plaintext, cb) => { + bcrypt.hash(plaintext, SALT_ROUNDS, cb, (err, hash) => { + if (err) return cb(err); + return cb(null, hash); + }); + }, + + // store hash in database + storePassword: (name, email, favColour, hashedPassword, cb) => { + dbConnection.query( + `INSERT INTO users (name, email, fav_colour, password_hash) VALUES ($1, $2, $3, $4)`, + [name, email, favColour, hashedPassword], + // `INSERT INTO users (name, email, fav_colour, password_hash) VALUES ('${name}', '${email}', '${favColour}', '${hashedPassword}')`, + // `INSERT INTO users (name, email, fav_colour, password_hash) VALUES ('Joe', 'Joe@dom.dom', '0947dd', '$2b$12$9KMMDuR2Le5n1.tl1LYqOuVCRXjwpIRfj0RafQa/mppqgNTD7.P8u')`, + (err, res) => { + if (err) return cb(err); + return cb(null, res); + } + ); + }, + + storeSession: (sessionID, email, cb) => { + console.log("session ID: ", sessionID) + dbConnection.query( + `INSERT INTO active_sessions (session_id, email) VALUES ($1, $2)`, + [sessionID, email], + (err, res) => { + if(err) return cb(err); + return cb(null, res, sessionID); + } + ) + } + + // takes in hash of password, compares against hash from database + // get user's hash from database + // comapare two hashes + // return true or false +}; + +module.exports = passwords; diff --git a/src/queries/getData.js b/src/queries/getData.js index 96aac45..0b2d736 100644 --- a/src/queries/getData.js +++ b/src/queries/getData.js @@ -3,7 +3,7 @@ const databaseConnection = require("../database/db_connection.js"); // qry is the db query we want to make const getData = (qry, cb) => { databaseConnection.query( - `SELECT users.name, users.fav_colour, items.name, items.id, items.description + `SELECT users.name, users.fav_colour, items.name, items.id, items.description , items.on_loan FROM items INNER JOIN users ON items.lender_id = users.id diff --git a/src/queries/postData.js b/src/queries/postData.js index c4018e2..56b1648 100644 --- a/src/queries/postData.js +++ b/src/queries/postData.js @@ -22,55 +22,60 @@ const addLoan = (itemId, borrowerId, cb) => { ); }; -const postData = (name, email, itemId, cb) => { - console.log("postData"); - let borrowerId; +const checkUser = (email, cb) => { dbConnection.query( `SELECT id FROM users WHERE email=$1`, [email], (err, res) => { - if (err) { - return cb(err); - } - if (res.rowCount > 0) { - borrowerId = res.rows[0].id; - addLoan(itemId, borrowerId, cb); - } else { - dbConnection.query( - `INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id`, - [name, email], - (err, res) => { - if (err) { - console.log(err); - return cb(err); - } - borrowerId = res.rows[0].id; - addLoan(itemId, borrowerId, cb); - } - ); - } + if (err) return cb(err); + if (res.rowCount === 1) cb(null, true); + else cb(null, false); } ); }; +const postData = (name, email, itemId, cb) => { + let borrowerId; + checkUser(email, (err, res) => { + if (err) return cb(err); + else if (res) { + borrowerId = res.rows[0].id; + addLoan(itemId, borrowerId, cb); + } else { + dbConnection.query( + `INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id`, + [name, email], + (err, res) => { + if (err) { + console.log(err); + return cb(err); + } + borrowerId = res.rows[0].id; + addLoan(itemId, borrowerId, cb); + } + ); + } + }); +}; const addItem = (name, description, lenderId, cb) => { + console.log("add item reached"); dbConnection.query( - `INSERT INTO items (name, description, lender_id) VALUES ('${name}', '${description}', ${lenderId}) RETURNING id`, + `INSERT INTO items (name, description, lender_id) VALUES ('${name}', '${description}', ${lenderId}) RETURNING id`, (err, res) => { if (err) { return cb(err); } - } - ) + return cb(null, res); + } + ); }; // Below function is for adding items (and new user if not already present) // WET. MAY DRY EVENTUALLY // params passed as arguments by handler/router const insertData = (name, email, itemName, itemDesc, favColour, cb) => { - console.log("insertData"); - console.log(name, email, itemName, itemDesc, favColour) + console.log("reached insert data"); let lenderId; dbConnection.query( `SELECT id FROM users WHERE email=$1`, @@ -80,9 +85,11 @@ const insertData = (name, email, itemName, itemDesc, favColour, cb) => { return cb(err); } if (res.rowCount > 0) { + console.log("user exists"); lenderId = res.rows[0].id; addItem(itemName, itemDesc, lenderId, cb); } else { + console.log("user doesnt exist"); dbConnection.query( `INSERT INTO users (name, email, fav_colour) VALUES ($1, $2, $3) RETURNING id`, [name, email, favColour], @@ -91,6 +98,7 @@ const insertData = (name, email, itemName, itemDesc, favColour, cb) => { return cb(err); } lenderId = res.rows[0].id; + console.log(lenderId); // Need to update these addItem(itemName, itemDesc, lenderId, cb); } @@ -100,4 +108,4 @@ const insertData = (name, email, itemName, itemDesc, favColour, cb) => { ); }; -module.exports = { postData, insertData }; +module.exports = { postData, checkUser, insertData }; diff --git a/src/router.js b/src/router.js index 8a3af23..ce01676 100644 --- a/src/router.js +++ b/src/router.js @@ -7,11 +7,14 @@ const router = (req, res) => { handlers.home(req, res); } else if (endpoint.startsWith("search?q=")) { handlers.search(req, res, endpoint); // some arguments maybe + } else if (endpoint === "register") { + console.log("reached register"); + handlers.register(req, res); } else if (endpoint === "request-item") { handlers.requestItem(req, res); } else if (endpoint === "add-item") { handlers.addItem(req, res, endpoint); // some arguments - } else if (endpoint === "testing") { + } else if (endpoint === "populate-all") { handlers.testData(req, res); } else if (endpoint === "success") { handlers.success(req, res); diff --git a/test/getData.test.js b/test/getData.test.js index 74666ec..09b2657 100644 --- a/test/getData.test.js +++ b/test/getData.test.js @@ -1,21 +1,25 @@ -const tape = require('tape'); -const runDbBuild = require('../src/database/db_build'); -const getData = require('../src/queries/getData'); +const tape = require("tape"); +const runDbBuild = require("../src/database/db_build"); +const getData = require("../src/queries/getData"); +const router = require("../src/router"); +const supertest = require("supertest"); // add postData here? -tape('tape is working', t => { - t.equals(1,1,'one is one'); - t.end() -}) +tape("tape is working", t => { + t.equals(1, 1, "one is one"); + t.end(); +}); -tape('test get data', t => { - runDbBuild((err) => { - t.error(err, 'No Error'); - const expected = 1; - getData((err, gotdata) => { - if (err) console.log(err); - t.deepEqual(gotdata[0].id, expected, 'getData should return itself'); +tape("test get data", t => { + runDbBuild(err => { + t.error(err, "No Error"); + supertest(router) + .get("/populate-all") + .expect(200) + .end((err, res) => { + t.error(err); + t.equal(res.statusCode, 200, "Should return 200"); t.end(); - }); - }) -}); \ No newline at end of file + }); + }); +}); diff --git a/test/passwords.test.js b/test/passwords.test.js new file mode 100644 index 0000000..9f67877 --- /dev/null +++ b/test/passwords.test.js @@ -0,0 +1,36 @@ +const tape = require("tape"); +const passwords = require("../src/passwords"); + +tape("password: tape is working", t => { + t.equals(1, 1, "one should equal one"); + t.end(); +}); + +tape("hash function works", t => { + passwords.hashPassword("qwerty", (err, hash) => { + t.error(err, "No error"); + t.equal( + hash.length, + 60, + "hash function should return string of 60 characters" + ); + t.end(); + }); +}); + +tape("password is stored in database", t => { + passwords.hashPassword("qwerty", (err, hash) => { + t.error(err, "No error"); + passwords.storePassword( + "joe", + "joe@joe.com", + "000000", + hash, + (err, res) => { + t.error(err, "No error"); + t.equal(res.rowCount, 1, "storePassword should return true"); + t.end(); + } + ); + }); +}); diff --git a/test/post-data.test.js b/test/post-data.test.js index a57c84a..7575c90 100644 --- a/test/post-data.test.js +++ b/test/post-data.test.js @@ -12,45 +12,66 @@ test("Initialise post-data tests", t => { t.end(); }); -test("Post request returns a status code of 302", t => { - runDbBuild((err, res) => { - t.error(err, "No error"); - +test("Registration", t => { + runDbBuild(err => { + t.error(err, "No Error"); let data = { - name: "anon", - email: "sang@gmail.com", - item: "5" + "reg-name": "anon", + "reg-email": "anon@anon.com", + "fav-colour": "#ffffff", + "reg-password": "password123" }; supertest(router) - .post("/request-item") - .send({ data }) - .expect(302) + .post("/register") + .send(JSON.stringify(data)) + .expect(200) .end((err, res) => { t.error(err); - t.equal(res.statusCode, 302, "Should return 302"); + t.equal(res.statusCode, 200, "registration endpoint should return 200"); t.end(); }); }); }); -test("Post request returns a status code of 302", t => { - runDbBuild((err, res) => { - t.error(err, "No error"); - console.log("res: ", res) - let data = { - name: "anon", - email: "sang@gmail.com", - itemName: "Scary thing", - itemDesc: "Super spooky" - }; - supertest(router) - .post("/add-item") - .send({ data }) - .expect(302) - .end((err, res) => { - t.error(err); - t.equal(res.statusCode, 302, "Should return 302"); - t.end(); - }); - }); -}); +// +// test("Post request returns a status code of 302", t => { +// runDbBuild((err, res) => { +// t.error(err, "No error"); +// +// let data = { +// name: "anon", +// email: "sang@gmail.com", +// item: "5" +// }; +// supertest(router) +// .post("/request-item") +// .send(data) +// .expect(302) +// .end((err, res) => { +// t.error(err); +// t.equal(res.statusCode, 302, "Should return 302"); +// t.end(); +// }); +// }); +// }); +// +// test("Post request returns a status code of 302", t => { +// runDbBuild((err, res) => { +// t.error(err, "No error"); +// let data = { +// name: "anon", +// email: "sang@gmail.com", +// itemName: "Scary thing", +// itemDesc: "Super spooky" +// }; +// supertest(router) +// .post("/add-item") +// .send(data) +// .expect(302) +// .end((err, res) => { +// t.error(err); +// t.equal(res.statusCode, 302, "Should return 302"); +// t.end(); +// }); +// }); +// }); diff --git a/testingcrypto.js b/testingcrypto.js new file mode 100644 index 0000000..0528794 --- /dev/null +++ b/testingcrypto.js @@ -0,0 +1,21 @@ +const crypto = require("crypto"); + + +function random(length = 24){ + return new Promise((resolve, reject) => { + crypto.randomBytes(48, (err, buffer) => { + if (err) { + reject(err); + } else { + resolve (buffer.toString("hex")) + } + }) + }) +} + + + + +var sessionID = random() +.then(dsdsfd => console.log(dsdsfd)) +