diff --git a/containers/api/package-lock.json b/containers/api/package-lock.json index 80ea8757..50aa6e88 100644 --- a/containers/api/package-lock.json +++ b/containers/api/package-lock.json @@ -19,6 +19,7 @@ "axios": "^1.4.0", "base32-decode": "^1.0.0", "base32-encode": "^2.0.0", + "bcrypt": "^5.1.0", "express-session": "^1.17.3", "hi-base32": "^0.5.1", "nanoid": "^3.3.4", @@ -38,6 +39,7 @@ "@nestjs/cli": "^9.0.0", "@nestjs/schematics": "^9.0.0", "@nestjs/testing": "^9.0.0", + "@types/bcrypt": "^5.0.0", "@types/express": "^4.17.13", "@types/jest": "29.5.0", "@types/node": "18.15.11", @@ -1425,6 +1427,39 @@ "node": ">=8" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", + "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@nestjs/cli": { "version": "9.4.2", "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-9.4.2.tgz", @@ -2131,6 +2166,15 @@ "@babel/types": "^7.3.0" } }, + "node_modules/@types/bcrypt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.0.tgz", + "integrity": "sha512-agtcFKaruL8TmcvqbndlqHPSJgsolhf/qPWchFlgnW1gECTN/nKbFcoFnvKAQRFfKbh+BO6A3SWdJu9t+xF3Lw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/body-parser": { "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", @@ -2734,6 +2778,11 @@ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -2783,6 +2832,17 @@ "node": ">=0.4.0" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -2934,6 +2994,36 @@ "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -3112,6 +3202,19 @@ } ] }, + "node_modules/bcrypt": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.0.tgz", + "integrity": "sha512-RHBS7HI5N5tEnGTmtR/pppX0mmDSBpQ4aCBsj7CEQfYXDcO74A8sIBYcJMuCsis2E81zDxeENYhv66oZwLiA+Q==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.10", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -3186,7 +3289,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3418,6 +3520,14 @@ "fsevents": "~2.3.2" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, "node_modules/chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -3604,6 +3714,14 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -3633,8 +3751,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/concat-stream": { "version": "1.6.2", @@ -3655,6 +3772,11 @@ "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -3817,6 +3939,11 @@ "node": ">=0.4.0" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -3834,6 +3961,14 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -4761,6 +4896,33 @@ "node": ">=12" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/fs-monkey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", @@ -4791,6 +4953,25 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -4846,7 +5027,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -4955,6 +5135,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "node_modules/hexoid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", @@ -4998,6 +5183,18 @@ "node": ">= 0.8" } }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -6267,7 +6464,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, "dependencies": { "semver": "^6.0.0" }, @@ -6282,7 +6478,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -6405,7 +6600,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -6430,6 +6624,34 @@ "node": ">=8" } }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -6521,6 +6743,11 @@ "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", "dev": true }, + "node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, "node_modules/node-emoji": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", @@ -6560,6 +6787,20 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -6581,6 +6822,17 @@ "node": ">=8" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -6871,7 +7123,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -7962,8 +8213,7 @@ "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/sisteransi": { "version": "1.0.5", @@ -8061,7 +8311,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -8219,6 +8468,46 @@ "node": ">=6" } }, + "node_modules/tar": { + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/terser": { "version": "5.17.1", "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.1.tgz", @@ -9098,6 +9387,14 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "node_modules/windows-release": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-4.0.0.tgz", diff --git a/containers/api/package.json b/containers/api/package.json index fdad87d1..bba9ac06 100644 --- a/containers/api/package.json +++ b/containers/api/package.json @@ -30,6 +30,7 @@ "axios": "^1.4.0", "base32-decode": "^1.0.0", "base32-encode": "^2.0.0", + "bcrypt": "^5.1.0", "express-session": "^1.17.3", "hi-base32": "^0.5.1", "nanoid": "^3.3.4", @@ -49,6 +50,7 @@ "@nestjs/cli": "^9.0.0", "@nestjs/schematics": "^9.0.0", "@nestjs/testing": "^9.0.0", + "@types/bcrypt": "^5.0.0", "@types/express": "^4.17.13", "@types/jest": "29.5.0", "@types/node": "18.15.11", diff --git a/containers/api/src/app.controller.ts b/containers/api/src/app.controller.ts index e396be5b..8c6949b1 100644 --- a/containers/api/src/app.controller.ts +++ b/containers/api/src/app.controller.ts @@ -6,7 +6,7 @@ /* By: apommier +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/06/17 01:00:00 by apommier #+# #+# */ -/* Updated: 2023/06/17 01:47:43 by apommier ### ########.fr */ +/* Updated: 2023/06/17 17:29:05 by apommier ### ########.fr */ /* */ /* ************************************************************************** */ @@ -419,7 +419,13 @@ export class AppController { return await this.chatService.getConv(req.user.username); } -// @UseGuards(JwtAuthGuard) + @UseGuards(JwtAuthGuard) + @Get('/convs') + async getConvs() { + return await this.chatService.findAll(); + } + + @UseGuards(JwtAuthGuard) @Post('/message') async postMessage(@Request() req, @Body() data: any) { //if i can post post ? @@ -432,16 +438,18 @@ export class AppController { id: null, } console.log(data); - return await this.chatService.createMessage(message); + return await this.chatService.createMessage(message, req.user.username); } - + + @UseGuards(JwtAuthGuard) @Post('/member') async getMember(@Body() data: any) { console.log(data); console.log(`get member= ${data.convId}`); return await this.chatService.findConv(data.convId); } - + + @UseGuards(JwtAuthGuard) @Post('/getMessage') async getMessage(@Body() data: any) { console.log(data); @@ -455,44 +463,75 @@ export class AppController { // res.json(messages); - } - + } + + @UseGuards(JwtAuthGuard) @Post('/ban') async banUser(@Body() data: any) { return await this.chatService.banUser(data.convId, data.username) } - + + @UseGuards(JwtAuthGuard) @Post('/name') async setName(@Body() data: any) { //find conv // data.convId return await this.chatService.setName(data.convId, data.name) } - + + @UseGuards(JwtAuthGuard) @Post('/invite') async inviteUser(@Body() data: any) { return await this.chatService.inviteUser(data.convId, data.username) } - + + @UseGuards(JwtAuthGuard) @Post('/password') async setPassword(@Body() data: any) { return await this.chatService.setPassword(data.convId, data.password) } - + + @UseGuards(JwtAuthGuard) + @Post('/verifyPassword') + async verifyPassword(@Body() data: any) { + return await this.chatService.verifyPassword(data.convId, data.password) + } + + @UseGuards(JwtAuthGuard) @Post('/admin') async setAdmin(@Body() data: any) { return await this.chatService.setAdmin(data.convId, data.username) } - + + @UseGuards(JwtAuthGuard) + @Post('/isAdmin') + async isAdmin(@Request() req, @Body() data: any) { + console.log("isdamin= ", req.user.username, " id=", data.convId) + return await this.chatService.isAdmin(data.convId, req.user.username) + } + + @UseGuards(JwtAuthGuard) @Post('/mute') async muteUser(@Body() data: any) { return await this.chatService.muteUser(data.convId, data.username) } - + + @UseGuards(JwtAuthGuard) @Post('/private') async setPrivate(@Body() data: any) { return await this.chatService.setPrivate(data.convId) } + @UseGuards(JwtAuthGuard) + @Post('/allowed') + async isAllowed(@Request() req, @Body() data: any) { + return await this.chatService.isAllowed(data.convId, req.user.username) + } + + @UseGuards(JwtAuthGuard) + @Post('/join') + async joinChannel(@Request() req, @Body() data: any) { + return await this.chatService.joinChannel(data.convId, req.user.username) + } } \ No newline at end of file diff --git a/containers/api/src/chat/chat.service.ts b/containers/api/src/chat/chat.service.ts index ed91847a..53a4c50f 100644 --- a/containers/api/src/chat/chat.service.ts +++ b/containers/api/src/chat/chat.service.ts @@ -6,7 +6,7 @@ /* By: apommier +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/06/17 01:00:25 by apommier #+# #+# */ -/* Updated: 2023/06/17 01:48:15 by apommier ### ########.fr */ +/* Updated: 2023/06/17 17:31:11 by apommier ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,6 +16,8 @@ import { Repository } from 'typeorm'; import { Conv } from '../model/chat.entity'; import { Message } from '../model/chat.entity'; +import * as bcrypt from 'bcrypt'; + import { ArrayContains } from "typeorm" import { query } from 'express'; import { InitializeOnPreviewAllowlist } from '@nestjs/core'; @@ -31,6 +33,10 @@ export class ChatService { return await this.chatRepository.save(conv); } +async findAll(): Promise { + return await this.chatRepository.find(); +} + async createConv(conv: Conv): Promise { return await this.chatRepository.save(conv); } @@ -49,8 +55,22 @@ async findConv(number: number){ return conv; } - async createMessage(message: Message): Promise { - return await this.messageRepository.save(message); + async createMessage(message: Message, username: string): Promise { + const conv = await this.findConv(message.convid); + if (conv.banned.find(item => item === username)) + return ; + if (conv.muted.find(item => item === username)) + return ; + return await this.messageRepository.save(message); + } + + async isAllowed(convId: number, username: string) { + const conv = await this.findConv(convId); + if (conv.banned.find(item => item === username)) + return (0); + if (conv.muted.find(item => item === username)) + return (0); + return (1); } async getMessages(convId: number): Promise { @@ -79,13 +99,26 @@ async inviteUser(convId: number, username: string) { //save user } + + async setPassword(convId: number, password: string) { //verify is user is admin ? const conv = await this.findConv(convId); - conv.password = password + const saltRounds = 10; + const hashedPassword = await bcrypt.hash(password, saltRounds); + // return hashedPassword; + conv.password = hashedPassword this.save(conv); } +async verifyPassword(convId: number, password: string) { + //verify is user is admin ? + const conv = await this.findConv(convId); + return await bcrypt.compare(password, conv.password); + + // conv.password = password +} + async muteUser(convId: number, username: string) { const conv = await this.findConv(convId); @@ -106,6 +139,16 @@ async setAdmin(convId: number, username: string) { this.save(conv); } +async isAdmin(convId: number, username: string) { + const conv = await this.findConv(convId); + + conv.admin = conv.admin || []; + if (conv.admin.find(item => item === username)) + return (1); + console.log("nope"); + return (0); +} + async setPrivate(convId: number) { const conv = await this.findConv(convId); if (conv.private === true) @@ -121,4 +164,14 @@ async setName(convId: number, name: string) { this.save(conv); } +async joinChannel(convId: number, username: string) { + const conv = await this.findConv(convId); + conv.members = conv.members || []; + if (conv.members.find(item => item === username)) + return ; + conv.members.push(username); + // conv.name = name; + this.save(conv); +} + } diff --git a/containers/react/src/components/Messages/Chats copy.jsx b/containers/react/src/components/Messages/Chats copy.jsx deleted file mode 100644 index 56b7c017..00000000 --- a/containers/react/src/components/Messages/Chats copy.jsx +++ /dev/null @@ -1,362 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* Chats.jsx :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: apommier +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2023/06/17 00:59:57 by apommier #+# #+# */ -/* Updated: 2023/06/17 01:24:24 by apommier ### ########.fr */ -/* */ -/* ************************************************************************** */ - -import React, { useState, useEffect, useRef } from "react"; -import io from 'socket.io-client'; -import '../../styles/Messages.css' -import styled from "styled-components"; -import DefaultPic from '../../assets/profile.jpg' -import api from '../../script/axiosApi'; -import { motion , AnimatePresence} from "framer-motion"; -import Modal from "./Modal"; - -import Message from "./Message" -// import Input from "./Input"; - -//react icons -import { TbSend } from 'react-icons/tb'; -import { ImBlocked } from 'react-icons/im'; -import { MdOutlineGroupAdd } from 'react-icons/md'; -import { GrAdd } from 'react-icons/gr'; -import { RiListSettingsLine } from 'react-icons/ri' - -import { Rank } from "../../DataBase/DataRank"; -import GreenAlert from "../Alert/GreenAlert"; -import RedAlert from "../Alert/RedAlert"; -import YellowAlert from "../Alert/YellowAlert"; -import ModalSetting from "./ModalSetting"; - - -const TouchDiv = styled.div` - margin-left: 10px; - margin-right: 4px; - margin-bottom: 21px; - margin-top: 21px; - cursor: pointer; - justify-content: space-around; - - &:hover { - color: #F4F3EF; - } -` - -const UserChat = styled.div ` - padding: 5px; - display: flex; - align-items: center; - gap: 5px; - color: white; - cursor: pointer; - - &:hover{ - background-color: #3e3c61; - } - &:active { - filter: black; - } -` - -// const SideSpan = styled.span` -// font-size: 18px; -// font-weight: 500; -// ` - -const SideP = styled.p` - font-size: 14px; - color: lightgray; - margin-left: 15px; -` - -//======================================================================================================== -//======================================================================================================== -// Logical part -//======================================================================================================== -//======================================================================================================== - - -function Chats(){ - - const [isLoading, setIsLoading] = useState(true); - const [conversations, setConversation] = useState([]); - const [user, setUser] = useState(null); - const [currentChat, setCurrentChat] = useState(false); // false is good? - const [messages, setMessage] = useState([]); - const [newMessages, setNewMessage] = useState(""); - const [incomingMessage, setIncomingMessage] = useState(""); - const socket = useRef(); - - useEffect(()=> { - - const getConv = async ()=>{ - try{ - const convs = await api.get("/conv") - const tmpUser = await api.get("/profile") - console.log(convs); - setUser(tmpUser.data); - setConversation(convs.data); - // return tmpUser; - - - // console.log(`user= ${tmpUser.data.username}`); - // console.log(`user= ${tmpUser.data.nickname}`); - // console.log(`user= ${tmpUser.data}`); - socket.current = io("ws://localhost:4001"); - console.log(`connection....`); - socket.current.emit('connection', {username: tmpUser.data.username}) - // const socket = io("http://localhost:4001", { - // query: { - // username: user.username, - // },}); - socket.current.on('message', (data) => { //data should be a message ? - console.log(`message received data= ${data.sender}`) - console.log(`message received data= ${data.convId}`) - console.log(`message received data= ${data.sender}`) - console.log(`current chat = ${currentChat}`) - setIncomingMessage(data); - }); - setIsLoading(false) - - } - catch(err){ - console.log(err); - } - }; - getConv(); - - }, []) - - useEffect(()=> { - if (currentChat) - console.log(currentChat.id) - // console.log(`result1 = ${currentChat.id !== incomingMessage.convId}`) - if (currentChat !== null && currentChat.id === incomingMessage.convId) - setMessage((prev) => [...prev, incomingMessage]); - }, [incomingMessage, currentChat]) - - useEffect(()=> { - const getMessage = async ()=> - { - const data = {convId: currentChat.id}; - - try { - const res = await api.post('/getMessage', data); - setMessage(res.data); - } catch(err) { - - } - } - getMessage(); - }, [currentChat]); - - const handleSubmit = async (e)=>{ - e.preventDefault(); - // console.log(`e= ${e.key}`) - // console.log(`name= ${user.username}`) - const message = { - sender: user.username, - text: newMessages, - convId: currentChat.id, - members: null - }; - try{ - console.log(`id= ${currentChat.id}`) - const res = await api.post('/message', message); - const convMember = await api.post('/member', message); - message.members = convMember.data.members; - console.log(convMember); - // console.log(`currentChat= ${currentChat.id}`) - - setMessage([...messages, res.data]); - setNewMessage(""); - socket.current.emit('sendMessage', message); - } - catch(err){ - console.log(err) - } - } - - const handleKeyPress = async (e)=>{ - // console.log(`e in press= ${e.key}`) - if (e.key !== "Enter") - return ; - // console.log(`name= ${user.username}`) - const message = { - sender: user.username, - text: newMessages, - convId: currentChat.id, - members: null - }; - try{ - console.log(`id= ${currentChat.id}`) - const res = await api.post('/message', message); - const convMember = await api.post('/member', message); - message.members = convMember.data.members; - console.log(convMember); - // console.log(`currentChat= ${currentChat.id}`) - - setMessage([...messages, res.data]); - setNewMessage(""); - socket.current.emit('sendMessage', message); - } - catch(err){ - console.log(err) - } - } - - const [friend, setFriend] = useState(""); - const [modalOpen, setModalOpen] = useState(false); - const [addFriend, setAddFriend] = useState(false); - const [block, setBlock] = useState(false); - const [setting, setSetting] = useState(false); - const close = () => setModalOpen(false); - const open = () => setModalOpen(true); - const closeAddFriend = () => setAddFriend(false); - const closeBlock = () => setBlock(false); - const closeSetting = () => setSetting(false); - - - const handleFriend = e => { - setFriend(e.target.value) - }; - - -//======================================================================================================== -//======================================================================================================== -// HTML -//======================================================================================================== -//======================================================================================================== - - - return ( -
- -
- profile - - {isLoading ? ( -

Loading...

- ) : ( -

{user.nickname}

- )} -
-
- - - (addFriend ? setAddFriend(false) : setAddFriend(true))}> - - {/* {console.log("find = ",find) && setFind(true)} */} - - null} - > - {addFriend && } - - {/* {console.log("find2 = ", find) && find && } */} - - - (block ? setBlock(false) : setBlock(true))} - > - - null} - > - {block && } - - - - {currentChat ? ( - - - (setting ? setSetting(false) : setSetting(true))} - > - - null} - > - {setting && } - - - - ):("")} -
-
-
-
- - - (modalOpen ? close() : open())} - > - - New Conversation - - {modalOpen && } - - - {conversations.map((c, index ) => { - return ( -
setCurrentChat(c)}> - - User -
- {c.name} - Desc? -
-
-
- - )})} -
- - { - currentChat ? ( - <> -
-
- {messages.map(m=>( - - ))} -
- {/* */} -
- setNewMessage(e.target.value)} - value={newMessages} - /> -
- -
-
-
- - ) : ( -
- Open a conversation -
- )} -
-
- // - ); -} - -export default Chats \ No newline at end of file diff --git a/containers/react/src/components/Messages/Chats.jsx b/containers/react/src/components/Messages/Chats.jsx index 279ae749..40d181dc 100644 --- a/containers/react/src/components/Messages/Chats.jsx +++ b/containers/react/src/components/Messages/Chats.jsx @@ -77,6 +77,8 @@ function Chats(){ const [conversations, setConversation] = useState([]); const [user, setUser] = useState(null); const [currentChat, setCurrentChat] = useState(false); // false is good? + const [isAdmin, setIsAdmin] = useState(false); // false is good? + // const [currentChat, setCurrentChat] = useState(false); // false is good? const [messages, setMessage] = useState([]); const [newMessages, setNewMessage] = useState(""); const [incomingMessage, setIncomingMessage] = useState(""); @@ -115,11 +117,30 @@ function Chats(){ }, []) useEffect(()=> { - if (currentChat) - console.log(currentChat.id) - // console.log(`result1 = ${currentChat.id !== incomingMessage.convId}`) - if (currentChat !== null && currentChat.id === incomingMessage.convId) - setMessage((prev) => [...prev, incomingMessage]); + + const updateChat = async ()=> { + // if (currentChat) + // console.log(currentChat.id) + if (currentChat) + { + + try { + const res = await api.post("/isAdmin", {convId: currentChat.id}) + console.log("isadmin= ", res.data) + setIsAdmin(res.data); + } catch (err) { + console.log(err); + } + } + // console.log(`result1 = ${currentChat.id !== incomingMessage.convId}`) + if (currentChat !== null && currentChat.id === incomingMessage.convId) + { + + setMessage((prev) => [...prev, incomingMessage]); + } + } + updateChat(); + }, [incomingMessage, currentChat]) useEffect(()=> { @@ -149,6 +170,10 @@ function Chats(){ }; try{ console.log(`id= ${currentChat.id}`) + const allowed = await api.post('/allowed', {convId: message.convId, username: user.username}); + console.log("allowed= ", allowed.data) + if (!allowed.data) + return ; const res = await api.post('/message', message); const convMember = await api.post('/member', message); message.members = convMember.data.members; @@ -358,6 +383,21 @@ function Chats(){ )} + {currentChat && isAdmin ? ( + + (setting ? setSetting(false) : setSetting(true))} + > + + null} + > + {setting && } + + + + ):("")} diff --git a/containers/react/src/components/Messages/Modal.jsx b/containers/react/src/components/Messages/Modal.jsx index 0f32b24c..87a41fc2 100644 --- a/containers/react/src/components/Messages/Modal.jsx +++ b/containers/react/src/components/Messages/Modal.jsx @@ -28,14 +28,23 @@ const Modal = ({handleClose}) => { const [selectTags, setSelectTag] = useState([{ id: 1, selectedOption: ''}]); const [selectedOptionArray, setSelectedOptionArray] = useState([]); const [users, setUsers] = useState([]); + const [user, setUser] = useState(); + const [convs, setConvs] = useState([]); + + const [channel, setChannel] = useState(''); useEffect(()=> { const getConv = async ()=>{ try { const tmpUsers = await api.get("/users"); + const tmpUser = await api.get("/profile"); + const tmpConvs = await api.get("/convs"); console.log("users=", tmpUsers.data); + console.log("convs=", tmpConvs.data); setUsers(tmpUsers.data); + setUser(tmpUser.data); + setConvs(tmpConvs.data); } catch(err){ console.log(err) } @@ -58,6 +67,15 @@ const Modal = ({handleClose}) => { console.log(selectTags) }; + const joinChannel = async () => { + try { + console.log("channel= ", channel) + await api.post("/join", {convId: channel}) + } catch(err) { + console.log(err); + } + }; + const saveSelectedOptions = () => { // const selectedOptions = selectTags.map((tag) => tag.selectedOption); const selectedOptions = selectTags.map((tag) => tag.selectedOption).filter((option) => option !== ''); @@ -108,24 +126,63 @@ const Modal = ({handleClose}) => { ))} - -
-
-

Selected Option:

-
    - {selectedOptionArray.map((option, index) => ( -
  • {option}
  • - ))} -
-
-
- Submit +
+ Submit - Cancel -
+ Cancel +
+ + + + {convs.length > 0 && ( + + )} + +
+ Join +
+ + + {/* {selectTags.map((selectTag) => ( +
+ +
+ ))} */} + + + + {/*
+ +
*/} +