diff --git a/.env b/.env index 5ded86e1..aae0c767 100644 --- a/.env +++ b/.env @@ -1,3 +1,8 @@ +#nessecarr var +#API_SECRET + + + # POSTGRES_USER=kinou # POSTGRES_PASSWORD=pass # POSTGRES_DB=postgreDB @@ -5,11 +10,37 @@ # POSTGRES_HOST=localhost # POSTGRES_HOST_AUTH_METHOD=trust -POSTGRES_HOST=127.0.0.1 -POSTGRES_PORT=5432 +#URL +NGINX_ENVSUBST_TEMPLATE_SUFFIX=".conf" + +# BASE_URL=http://localhost +BASE_URL=localhost +REACT_APP_BASE_URL=localhost +REDIRECT_URI=http://localhost/api/auth/login +#postgres var +# POSTGRES_HOST=127.0.0.1 +# DB_TYPE=postgres +POSTGRES_HOST=postgresql POSTGRES_USER=postgres POSTGRES_PASSWORD=pass POSTGRES_DATABASE=postgres -PORT=3000 MODE=DEV -RUN_MIGRATIONS=true \ No newline at end of file + +#port +API_PORT=3000 +# REACT_PORT=3000 (current = 8080) +NGINX_PORT=80 +PONG_PORT=4000 +CHAT_PORT=4001 +POSTGRES_PORT=5432 + +#???? +RUN_MIGRATIONS=true +REACT_HOST=0.0.0.0 + + +#auth var +JWT_SECRET=secrethere +# REDIRECT_URI=http://localhost:80/api/auth/login +API_SECRET=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 +CLIENT_UID=u-s4t2ud-6d29dfa49ba7146577ffd8bf595ae8d9e5aaa3e0a9615df18777171ebf836a41 \ No newline at end of file diff --git a/conf/nginx.conf b/conf/nginx.conf index f4093a53..8af41775 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -2,15 +2,14 @@ server { # listen 443 ssl; # listen 80 ssl; # listen 443 ssl; - listen 80; - + # listen ${NGINX_PORT}; + listen 80; location /{ proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://react_app:8080; } @@ -19,7 +18,6 @@ server { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://api:3000/api; } } \ No newline at end of file diff --git a/containers/api/package-lock.json b/containers/api/package-lock.json index e925e7b2..50aa6e88 100644 --- a/containers/api/package-lock.json +++ b/containers/api/package-lock.json @@ -19,9 +19,11 @@ "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", + "otpauth": "^9.1.2", "passport": "^0.6.0", "passport-jwt": "^4.0.1", "passport-local": "^1.0.0", @@ -37,9 +39,11 @@ "@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", + "@types/qrcode": "^1.5.0", "@types/supertest": "^2.0.11", "@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/parser": "^5.0.0", @@ -1423,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", @@ -2129,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", @@ -2304,6 +2350,15 @@ "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", "dev": true }, + "node_modules/@types/qrcode": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.0.tgz", + "integrity": "sha512-x5ilHXRxUPIMfjtM+1vf/GPTRWZ81nqscursm5gMznJeK9M0YnZ1c3bEvRLQ0zSSgedLx1J6MGL231ObQGGhaA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", @@ -2723,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", @@ -2772,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", @@ -2923,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", @@ -3101,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", @@ -3175,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" @@ -3407,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", @@ -3593,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", @@ -3622,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", @@ -3644,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", @@ -3806,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", @@ -3823,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", @@ -4750,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", @@ -4780,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", @@ -4835,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", @@ -4944,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", @@ -4987,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", @@ -6099,6 +6307,14 @@ "npm": ">=6" } }, + "node_modules/jssha": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/jssha/-/jssha-3.3.0.tgz", + "integrity": "sha512-w9OtT4ALL+fbbwG3gw7erAO0jvS5nfvrukGPMWIAoea359B26ALXGpzy4YJSp9yGnpUvuvOw1nSjSoHDfWSr1w==", + "engines": { + "node": "*" + } + }, "node_modules/jwa": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", @@ -6248,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" }, @@ -6263,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" } @@ -6386,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" }, @@ -6411,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", @@ -6502,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", @@ -6541,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", @@ -6562,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", @@ -6685,6 +6956,17 @@ "node": ">=0.10.0" } }, + "node_modules/otpauth": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/otpauth/-/otpauth-9.1.2.tgz", + "integrity": "sha512-iI5nlVvMFP3aTPdjG/fnC4mhVJ/KZOSnBrvo/VnYHUwlTp9jVLjAe2B3i3pyCH+3/E5jYQRSvuHk/8oas3870g==", + "dependencies": { + "jssha": "~3.3.0" + }, + "funding": { + "url": "https://github.com/hectorm/otpauth?sponsor=1" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -6841,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" } @@ -7932,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", @@ -8031,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" } @@ -8189,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", @@ -9068,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 74c414b2..bba9ac06 100644 --- a/containers/api/package.json +++ b/containers/api/package.json @@ -30,9 +30,11 @@ "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", + "otpauth": "^9.1.2", "passport": "^0.6.0", "passport-jwt": "^4.0.1", "passport-local": "^1.0.0", @@ -48,9 +50,11 @@ "@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", + "@types/qrcode": "^1.5.0", "@types/supertest": "^2.0.11", "@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/parser": "^5.0.0", diff --git a/containers/api/src/app.controller.ts b/containers/api/src/app.controller.ts index 489c3ad8..afef9106 100644 --- a/containers/api/src/app.controller.ts +++ b/containers/api/src/app.controller.ts @@ -1,3 +1,15 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* app.controller.ts :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: apommier +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/06/17 01:00:00 by apommier #+# #+# */ +/* Updated: 2023/06/18 13:16:23 by apommier ### ########.fr */ +/* */ +/* ************************************************************************** */ + import { Controller, Request, Req, Get, Post, UseGuards, Redirect, Res, Body, UploadedFile, UseInterceptors} from '@nestjs/common'; import { FileInterceptor } from '@nestjs/platform-express'; @@ -9,7 +21,16 @@ import { UsersService } from './users/users.service'; import { MatchLog } from './model/user.entity' import { generate } from 'rxjs'; -import { generateQRcode } from './users/2fa'; + +// import { generateQRcode } from './users/2fa'; +import { generateOTP } from './users/2fa'; +import { VerifyOTP } from './users/2fa'; +import { ValidateOTP } from './users/2fa'; +import { privateDecrypt } from 'crypto'; + + +//2fa + // import { initStorage, getUser, setUser } from './storage'; @@ -52,6 +73,13 @@ export class AppController { return await this.userService.findOne(data.username); } + @UseGuards(JwtAuthGuard) + @Get('/users') + async getUsers( @Body() data: any) { + console.log(`usernamewwww= ${data.username}`) + return await this.userService.findAll(); + } + @UseGuards(JwtAuthGuard) @Get('/friends') async getFriends(@Request() req) { @@ -60,16 +88,62 @@ export class AppController { } @UseGuards(JwtAuthGuard) - @Post('/friend') + @Post('/friend')//need to do it 2 time when user accept one for each async newFriend(@Request() req, @Body() data: any) { // return await this.userService.getFriends(req.user.username); console.log(`user= ${req.user.username}`) const user = await this.userService.findOne(req.user.username) + if (!user) + return (0); + //create personnal conv for user + //await this.userService.addFriend(user, data.username); + + + + // const amIhere = data.members.includes(req.user.username); + // if (!amIhere) + const conv = { + id: null, + name: req.user.username + ", " + data.username, + banned: [], + admin: [], + muted: [], + members: [], + owner: req.user.username, + password: null, + messages: null, + group: false, + private: false, + + }; + conv.members.push(req.user.username); + conv.members.push(data.username); + await this.chatService.createConv(conv); + return await this.userService.addFriend(user, data.username); } @UseGuards(JwtAuthGuard) - @Get('/invite') + @Post('/block') + async newBlocked(@Request() req, @Body() data: any) { + // return await this.userService.getFriends(req.user.username); + console.log(`user= ${req.user.username}`) + const user = await this.userService.findOne(req.user.username) + return await this.userService.addBlocked(user, data.username); + } + + @UseGuards(JwtAuthGuard) + @Post('/invite') + async newInvite(@Request() req, @Body() data: any) { + console.log(`user= ${req.user.username}`) + const user = await this.userService.findOne(data.username) + if (!user) + return (0); + return await this.userService.newInvite(user, req.user.username); + } + + @UseGuards(JwtAuthGuard) + @Get('/inviteRequest') async getInvite(@Request() req) { // return await this.userService.getFriends(req.user.username); console.log(`useawdawd\n\n\nr= ${req.user.username}`) @@ -77,6 +151,15 @@ export class AppController { return await this.userService.getInvite(req.user.username); } + @UseGuards(JwtAuthGuard) + @Post('/refuseInvite') + async refuseInvite(@Request() req, @Body() data: any) { + // return await this.userService.getFriends(req.user.username); + // console.log(`useawdawd\n\n\nr= ${req.user.username}`) + const user = await this.userService.findOne(req.user.username) + return await this.userService.refuseInvite(user, data.username); + } + @UseGuards(JwtAuthGuard) @Post('/status') async setStatus(@Request() req, @Body() data: any) { @@ -216,21 +299,31 @@ export class AppController { //======================================================================================================== //======================================================================================================== -@Redirect('http://localhost/token', 302) +// import { Prisma } from "@prisma/client"; +// import { Request, Response, NextFunction } from "express"; +// import { prisma } from "../server"; + + + +@Redirect('http://' + process.env.BASE_URL + '/token', 302) @Get('auth/login') async login2(@Req() request: Request) { const url = request.url; const user = await this.loginClass.Login42(url); console.log(`user in auth/login= ${user}`); - const data = this.authService.login(user); + console.log(`user in auth/login= ${user.username}`); + const data = await this.authService.login(user); console.log(`all data in api = ${data}`) const myJSON = JSON.stringify(data); console.log(`all data json version= ${myJSON}`) console.log(`data in api = ${(await data).access_token}`) + // console.log(`data i = ${(await data).access_token}`) const token = (await data).access_token; - return { url: `http://localhost/token?data=${encodeURIComponent(JSON.stringify(token))}` }; + // console + await this.userService.save(user); + return { url: 'http://' + process.env.BASE_URL + `/token?data=${encodeURIComponent(JSON.stringify(token))}` }; } @UseGuards(JwtAuthGuard) @@ -238,17 +331,49 @@ export class AppController { async get2fa(@Request() req) { const user = await this.userService.findOne(req.user.username); - return user.doubleAuth; + return user.otp_enabled; } @UseGuards(JwtAuthGuard) - @Get('/QRcode') - async createQrCode(@Request() req) + @Post('/otp') + async createOTP(@Request() req) { - return (await generateQRcode(req)); + const user = await this.userService.findOne(req.user.username); + // const user2 = await this.userService.findOne(req.user.username); + const res = await generateOTP(user); + await this.userService.save(user); + // console.log(user); + return res; } + @UseGuards(JwtAuthGuard) + @Post('/verifyOtp') + async verifyOTP(@Request() req, @Body() data: any) + { + const user = await this.userService.findOne(req.user.username); + const res = await VerifyOTP(user, data.token) + await this.userService.save(user); + return res + } + + @UseGuards(JwtAuthGuard) + @Post('/validateOtp') + async validateOTP(@Request() req, @Body() data: any) + { + const user = await this.userService.findOne(req.user.username); + const res = await ValidateOTP(user, data.token) + // await this.userService.save(user); + return res + } + +// @UseGuards(JwtAuthGuard) +// @Get('/QRcode') +// async createQrCode(@Request() req) +// { +// return (await generateQRcode(req)); +// } + @UseGuards(JwtAuthGuard) @Post('/quit') async setOffline(@Request() req) { @@ -267,34 +392,42 @@ export class AppController { //======================================================================================================== //======================================================================================================== + @UseGuards(JwtAuthGuard) @Post('/conv') async createConv(@Request() req, @Body() data: any) { ///create conv and return it ? id? - console.log(`data post /conv= ${data}`); + // console.log(`data post /conv= ${data}`); + // console.log(`data post /conv= ${data.members}`); + // console.log(`data post /conv= ${data.name}`); + + // const param = data; + const amIhere = data.members.includes(req.user.username); + if (!amIhere) + data.members.push(req.user.username); + data.admin = []; + data.admin.push(req.user.username); // let test = {id: 2, members: "cc"}; + data.owner = req.user.username; + data.group = true; return await this.chatService.createConv(data); // res.json(messages); } -// @UseGuards(JwtAuthGuard) + @UseGuards(JwtAuthGuard) @Get('/conv') - async getConv(@Request() req, @Body() data: any) { - ///create conv and return it ? id? - // console.log(`data get /conv= ${data}`); - // let test = {id: 2, members: "cc"}; - - // let tab = [data.member, "test"]; - // console.log(`tab= ${tab}`); - return await this.chatService.getConv(data.member); - // return await this.chatService.getConv(req.user.username); - - - // res.json(messages); + async getConv(@Request() req) { + 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 ? @@ -307,16 +440,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); @@ -330,6 +465,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/auth/auth.module.ts b/containers/api/src/auth/auth.module.ts index 68f7047e..7d5b4695 100644 --- a/containers/api/src/auth/auth.module.ts +++ b/containers/api/src/auth/auth.module.ts @@ -28,7 +28,7 @@ import { JwtStrategy } from './jwt.strategy'; PassportModule, JwtModule.register({ secret: jwtConstants.secret, - signOptions: { expiresIn: '60000s' }, + // signOptions: { expiresIn: '60000s' }, }), ], providers: [AuthService, LocalStrategy, JwtStrategy], diff --git a/containers/api/src/auth/auth.service.ts b/containers/api/src/auth/auth.service.ts index db08d5b2..8f0a2455 100644 --- a/containers/api/src/auth/auth.service.ts +++ b/containers/api/src/auth/auth.service.ts @@ -1,6 +1,7 @@ import { Injectable } from '@nestjs/common'; import { UsersService } from '../users/users.service'; import { JwtService } from '@nestjs/jwt'; +import { User } from 'src/model/user.entity'; @Injectable() export class AuthService { @@ -19,13 +20,13 @@ export class AuthService { return null; } - async login(user) { - const myJSON = JSON.stringify(user); + async login(user: User) { + // const myJSON = JSON.stringify(user); // console.log(`in login all user= ${myJSON}`) - // console.log(`in login user= ${user.username}`) + console.log(`in login user= ${user.username}`) const payload = { username: user.username, sub: user.userId }; - // console.log(`in login payload name= ${payload.username}`) - // console.log(`in login payload sub= ${payload.sub}`) + console.log(`in login payload name= ${payload.username}`) + console.log(`in login payload sub= ${payload.sub}`) return { access_token: this.jwtService.sign(payload), }; diff --git a/containers/api/src/auth/constants.ts b/containers/api/src/auth/constants.ts index efce4f67..4ab5a56d 100644 --- a/containers/api/src/auth/constants.ts +++ b/containers/api/src/auth/constants.ts @@ -1,3 +1,4 @@ export const jwtConstants = { - secret: 'DO NOT USE THIS VALUE. INSTEAD, CREATE A COMPLEX SECRET AND KEEP IT SAFE OUTSIDE OF THE SOURCE CODE.', + // secret: 'DO NOT USE THIS VALUE. INSTEAD, CREATE A COMPLEX SECRET AND KEEP IT SAFE OUTSIDE OF THE SOURCE CODE.', + secret: process.env.JWT_SECRET, }; \ No newline at end of file diff --git a/containers/api/src/auth/login42.ts b/containers/api/src/auth/login42.ts index 0ec25ef8..8f44f2e4 100644 --- a/containers/api/src/auth/login42.ts +++ b/containers/api/src/auth/login42.ts @@ -24,10 +24,11 @@ export class loginClass { const data = { grant_type: 'authorization_code', - client_id: 'u-s4t2ud-6d29dfa49ba7146577ffd8bf595ae8d9e5aaa3e0a9615df18777171ebf836a41', - client_secret: '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', + client_id: process.env.CLIENT_UID || 'u-s4t2ud-6d29dfa49ba7146577ffd8bf595ae8d9e5aaa3e0a9615df18777171ebf836a41', + // client_secret: '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', + client_secret: process.env.API_SECRET, code: code, - redirect_uri: 'http://localhost:80/api/auth/login', + redirect_uri: process.env.REDIRECT_URI || 'http://' + process.env.REACT_APP_BASE_URL + '/api/auth/login', }; try { @@ -64,11 +65,15 @@ export class loginClass { loss: 0, rank: 1200, userId: userId, + otp_base32: null, children: null, status: 1, - doubleAuth: 0, + // doubleAuth: 0, + otp_enabled: false, + otp_verified: false, friendRequest: null, friends: null, + blocked: null, photo: null, }; await this.usersService.create(user); diff --git a/containers/api/src/chat/chat.service.ts b/containers/api/src/chat/chat.service.ts index eb07634a..25a5a626 100644 --- a/containers/api/src/chat/chat.service.ts +++ b/containers/api/src/chat/chat.service.ts @@ -1,7 +1,14 @@ -// import { Injectable } from '@nestjs/common'; - -// @Injectable() -// export class ConvService {} +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* chat.service.ts :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: apommier +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/06/17 01:00:25 by apommier #+# #+# */ +/* Updated: 2023/06/18 13:14:51 by apommier ### ########.fr */ +/* */ +/* ************************************************************************** */ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; @@ -9,8 +16,11 @@ 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'; @Injectable() @@ -19,19 +29,19 @@ export class ChatService { @InjectRepository(Message) private messageRepository: Repository, ) {} + async save(conv: Conv): Promise { + 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); } - - -// SELECT "conv"."id" AS "conv_id", "conv"."members" AS "conv_members", "conv"."name" AS "conv_name", "conv"."banned" AS "conv_banned", "conv"."admin" AS "conv_admin", "conv"."messages" AS "conv_messages" FROM "conv" "conv" WHERE $1 = ANY("conv"."members") - - -// import { createConnection } from 'typeorm'; - async getConv(username: string): Promise{ - username = "sadjigui" const convs = await this.chatRepository.query("SELECT * FROM \"conv\" WHERE $1 = ANY (ARRAY[members]);", [username]) console.log(`convs= ${convs}`) return convs; @@ -44,56 +54,123 @@ async findConv(number: number){ return conv; } -// Usage -// const user = 'user1'; -// findConvsContainingUser(user) -// .then((convs) => { -// console.log('Convs containing user:', convs); -// }) -// .catch((error) => { -// console.error('Error:', error); -// }); - // return await this.chatRepository.findOneBy({ - // members: { $in: [username] }, - // }); - - // return await this.chatRepository.find() + async createMessage(message: Message, username: string): Promise { + const conv = await this.findConv(message.convid); + if (conv.banned && conv.banned.find(item => item === username)) + return ; + if (conv.muted && conv.muted.find(item => item === username)) + return ; + return await this.messageRepository.save(message); + } - - // return await this.chatRepository.findOneBy({ - // members: ArrayContains(["apommier"]), - // }) - - // console.log(`get conv username= ${username} `) - // let test = await this.chatRepository.find({ - // where : { - // members: { $all: ["apommier"] }, - // }}) - // console.log(`test= ${test}`) - // return test -// } - - - - - -// -// message -// - - async createMessage(message: Message): Promise { - return await this.messageRepository.save(message); + async isAllowed(convId: number, username: string) { + const conv = await this.findConv(convId); + if (conv.banned && conv.banned.find(item => item === username)) + return (0); + if (conv.muted && conv.muted.find(item => item === username)) + return (0); + return (1); } async getMessages(convId: number): Promise { -// return await this.messageRepository.find({ -// where: { -// convId: convId, -// }, -// }); const convs = await this.chatRepository .query("SELECT * FROM \"message\" WHERE $1 = message.convid;", [convId]) return (convs) } + +async banUser(convId: number, username: string) { + const conv = await this.findConv(convId); + + conv.banned = conv.banned || []; + if (conv.banned.find(item => item === username)) + return (1); + conv.banned.push(username); + this.save(conv); +} + +async inviteUser(convId: number, username: string) { + // const conv = await this.findConv(convId); + // this.save(conv); + + //find user + //add in chanInvite chanID + //save user +} + + + +async setPassword(convId: number, password: string) { + //verify is user is admin ? + const conv = await this.findConv(convId); + 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); + + conv.muted = conv.muted || []; + if (conv.muted.find(item => item === username)) + return (1); + conv.muted.push(username); + this.save(conv); +} + +async setAdmin(convId: number, username: string) { + const conv = await this.findConv(convId); + + conv.admin = conv.admin || []; + if (conv.admin.find(item => item === username)) + return (1); + conv.admin.push(username); + 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) + conv.private = false; + else + conv.private = true; + this.save(conv); +} + +async setName(convId: number, name: string) { + const conv = await this.findConv(convId); + conv.name = name; + 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/api/src/config/config.service.ts b/containers/api/src/config/config.service.ts index cd1ded6f..efb443aa 100644 --- a/containers/api/src/config/config.service.ts +++ b/containers/api/src/config/config.service.ts @@ -6,7 +6,7 @@ /* By: apommier +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/04/09 14:53:49 by apommier #+# #+# */ -/* Updated: 2023/06/01 13:07:12 by apommier ### ########.fr */ +/* Updated: 2023/06/12 14:51:44 by apommier ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,11 +14,11 @@ import { TypeOrmModuleOptions } from '@nestjs/typeorm'; export const getTypeOrmConfig = (): TypeOrmModuleOptions => ({ type: 'postgres', - host: 'postgresql', - port: 5432, - username: 'postgres', - password: 'pass', - database: 'postgres', + host: process.env.POSTGRES_HOST || 'postgresql', + port: parseInt(process.env.POSTGRES_PORT, 10) || 5432, + username: process.env.POSTGRES_USER || 'postgres', + password: process.env.POSTGRES_PASSWORD || 'pass', + database: process.env.POSTGRES_DATABASE || 'postgres', entities: ["dist/**/*.entity.js"], // entities: [join(__dirname, '**', '*.entity.{ts,js}')] // entities: ['**/*.entity{.ts,.js}'], //basic diff --git a/containers/api/src/main.ts b/containers/api/src/main.ts index c3a0187d..aafa4d84 100644 --- a/containers/api/src/main.ts +++ b/containers/api/src/main.ts @@ -1,6 +1,10 @@ import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import * as session from 'express-session'; +import * as dotenv from 'dotenv'; + +dotenv.config(); +console.log(process.env); // async function bootstrap() { // const app = await NestFactory.create(AppModule); @@ -27,6 +31,6 @@ async function bootstrap() { saveUninitialized: false, }), ); - await app.listen(3000); + await app.listen(parseInt(process.env.API_PORT) || 3000); } bootstrap(); \ No newline at end of file diff --git a/containers/api/src/model/chat.entity.ts b/containers/api/src/model/chat.entity.ts index 246197ac..b81950d6 100644 --- a/containers/api/src/model/chat.entity.ts +++ b/containers/api/src/model/chat.entity.ts @@ -1,3 +1,15 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* chat.entity.ts :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: apommier +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/06/17 01:00:20 by apommier #+# #+# */ +/* Updated: 2023/06/17 01:31:29 by apommier ### ########.fr */ +/* */ +/* ************************************************************************** */ + import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, BaseEntity } from 'typeorm'; @Entity() @@ -8,20 +20,32 @@ import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, BaseEntity } @Column('text', { array: true, nullable: true }) members: string[]; - @Column({ nullable: true }) + @Column({ default: "Unnamed Conv" }) name: string @Column({ nullable: true }) group: boolean + @Column({ nullable: true }) + private: boolean + // @Column() // members: string;// arry ??? one to many ??? - @Column({ nullable: true }) - banned: string;// arry ??? one to many ??? + @Column('text', { array: true, nullable: true }) + banned: string[]; + + @Column('text', { array: true, nullable: true }) + muted: string[]; + + @Column('text', { array: true, nullable: true }) + admin: string[]; @Column({ nullable: true }) - admin: string;// arry ??? one to many ??? + owner: string; + + @Column({ nullable: true }) + password: string; @Column({ nullable: true }) messages: string; diff --git a/containers/api/src/model/user.entity.ts b/containers/api/src/model/user.entity.ts index c0413098..5ddd7709 100644 --- a/containers/api/src/model/user.entity.ts +++ b/containers/api/src/model/user.entity.ts @@ -20,6 +20,18 @@ export class User { @PrimaryGeneratedColumn() id: number; + // otp_enabled Boolean @default(false) + // otp_verified Boolean @default(false) + + @Column({ default: false }) + otp_enabled: boolean; + + @Column({ default: false }) + otp_verified: boolean; + + @Column({ nullable: true }) + otp_base32: string; + @Column({ nullable: true }) nickname: string; @@ -47,8 +59,8 @@ export class User { @Column({ default: 0 }) userId: number; - @Column({ default: 0 }) - doubleAuth: number; + // @Column({ default: 0 }) + // doubleAuth: number; @Column('text', { array: true, nullable: true }) friendRequest: string[]; @@ -56,6 +68,9 @@ export class User { @Column('text', { array: true, nullable: true }) friends: string[]; + @Column('text', { array: true, nullable: true }) + blocked: string[]; + @OneToMany(() => MatchLog, (child) => child.parent, { eager: true }) children: MatchLog[]; diff --git a/containers/api/src/users/2fa.ts b/containers/api/src/users/2fa.ts index 2f1a3147..38a0924e 100644 --- a/containers/api/src/users/2fa.ts +++ b/containers/api/src/users/2fa.ts @@ -1,6 +1,128 @@ -import crypto from 'crypto'; +// import crypto from 'crypto'; import base32Decode from 'base32-decode'; +import crypto from "crypto"; +import * as OTPAuth from "otpauth"; +import { encode } from "hi-base32"; + +import * as qr from 'qrcode'; + +// [...] Register user + +// [...] Login user + +// [...] Generate OTP + +const generateRandomBase32 = async () => { + const {randomBytes} = await import('crypto'); + const buffer = randomBytes(15); + const base32 = encode(buffer).replace(/=/g, "").substring(0, 24); + return base32; + }; + +export const generateOTP = async (user) => { + try { + const base32_secret = await generateRandomBase32(); + + let totp = new OTPAuth.TOTP({ + issuer: "Localhost", + label: "OnlinePong", + algorithm: "SHA1", + digits: 6, + period: 15, + secret: base32_secret, + }); + + let otpauth_url = totp.toString(); + const qrCodeDataUrl = await qr.toDataURL(otpauth_url, { errorCorrectionLevel: 'H' }); + + const filePath = 'qrcode.png'; // Specify the file path where the QR code should be saved + + qr.toFile(filePath, qrCodeDataUrl, (error) => { + if (error) { + console.error(error); + // Handle the error appropriately + return; + } + // QR code image has been generated and saved to the file + // Or, you can create a buffer of the image data directly + }) + + + + + + + const res = { + otpauth_url: otpauth_url, + base32_secret: base32_secret + } + + console.log("res= ", res) + + //update db with otp var + user.otp_enabled = true; + user.otp_base32 = base32_secret; + return (res) + + } catch (error) { + console.log(error) + } + }; + + export const VerifyOTP = async (user, token: string) => { + try { + let totp = new OTPAuth.TOTP({ + issuer: "Localhost", + label: "OnlinePong", + algorithm: "SHA1", + digits: 6, + period: 15, + secret: user.otp_base32, + }); + + let delta = totp.validate({ token }); + + if (delta === null) { + console.log("error verify token") + return ("error verify token") + } + else + { + user.otp_verified = true; + console.log("token verified") + } + } catch (error) { + console.log(error) + } + }; + + export const ValidateOTP = async (user, token: string) => { + try { + let totp = new OTPAuth.TOTP({ + issuer: "Localhost", + label: "OnlinePong", + algorithm: "SHA1", + digits: 6, + period: 15, + secret: user.otp_base32, + }); + let delta = totp.validate({ token }); + + if (delta === null) { + console.log("error validate token") + return ("error validate token") + } + else + { + // user.otp_verified = true; + console.log("token validated") + } + } catch (error) { + console.log(error) + } + }; + // import { randomBytes} from 'crypto'; // import { promisify } from 'util'; @@ -33,48 +155,48 @@ import base32Decode from 'base32-decode'; // type QRcode = any; -export function generateHOTP(secret, counter) { - const decodedSecret = base32Decode(secret, 'RFC4648'); +// export function generateHOTP(secret, counter) { +// const decodedSecret = base32Decode(secret, 'RFC4648'); - const buffer = Buffer.alloc(8); - for (let i = 0; i < 8; i++) { - buffer[7 - i] = counter & 0xff; - counter = counter >> 8; - } - - // Step 1: Generate an HMAC-SHA-1 value - const hmac = crypto.createHmac('sha1', Buffer.from(decodedSecret)); - hmac.update(buffer); - const hmacResult = hmac.digest(); - - // Step 2: Generate a 4-byte string (Dynamic Truncation) - const offset = hmacResult[hmacResult.length - 1] & 0xf; - const code = - ((hmacResult[offset] & 0x7f) << 24) | - ((hmacResult[offset + 1] & 0xff) << 16) | - ((hmacResult[offset + 2] & 0xff) << 8) | - (hmacResult[offset + 3] & 0xff); - - // Step 3: Compute an HOTP value - return code % 10 ** 6; - } +// const buffer = Buffer.alloc(8); +// for (let i = 0; i < 8; i++) { +// buffer[7 - i] = counter & 0xff; +// counter = counter >> 8; +// } -export function generateTOTP(secret, window = 0) -{ - const counter = Math.floor(Date.now() / 30000); - return generateHOTP(secret, counter + window); -} +// // Step 1: Generate an HMAC-SHA-1 value +// const hmac = crypto.createHmac('sha1', Buffer.from(decodedSecret)); +// hmac.update(buffer); +// const hmacResult = hmac.digest(); -export function verifyTOTP(token, secret, window = 1) -{ - for (let errorWindow = -window; errorWindow <= +window; errorWindow++) - { - const totp = generateTOTP(secret, errorWindow); - if (token === totp) - return true; - } - return false; -} +// // Step 2: Generate a 4-byte string (Dynamic Truncation) +// const offset = hmacResult[hmacResult.length - 1] & 0xf; +// const code = +// ((hmacResult[offset] & 0x7f) << 24) | +// ((hmacResult[offset + 1] & 0xff) << 16) | +// ((hmacResult[offset + 2] & 0xff) << 8) | +// (hmacResult[offset + 3] & 0xff); + +// // Step 3: Compute an HOTP value +// return code % 10 ** 6; +// } + +// export function generateTOTP(secret, window = 0) +// { +// const counter = Math.floor(Date.now() / 30000); +// return generateHOTP(secret, counter + window); +// } + +// export function verifyTOTP(token, secret, window = 1) +// { +// for (let errorWindow = -window; errorWindow <= +window; errorWindow++) +// { +// const totp = generateTOTP(secret, errorWindow); +// if (token === totp) +// return true; +// } +// return false; +// } @@ -94,86 +216,86 @@ export function verifyTOTP(token, secret, window = 1) // import * as base32Encode from 'base32-encode'; // import { base32Encode } from 'base32-encode'; // import base32Encode from 'base32-encode'; -import { encode } from 'thirty-two'; +// import { encode } from 'thirty-two'; -// ... +// // ... -import * as qrcode from 'qrcode'; -import * as fs from 'fs'; +// import * as qrcode from 'qrcode'; +// import * as fs from 'fs'; -import { nanoid } from "nanoid"; -// import * as nanoid from 'nanoid' +// import { nanoid } from "nanoid"; +// // import * as nanoid from 'nanoid' -export async function generateQRcode(req) -{ - // const base32Encode = (await import('base32-encode')); - // const nanoid = (await import('nanoid')); +// export async function generateQRcode(req) +// { +// // const base32Encode = (await import('base32-encode')); +// // const nanoid = (await import('nanoid')); - // const util = (await import('util')); - // const qrcode = (await import('qrcode')); +// // const util = (await import('util')); +// // const qrcode = (await import('qrcode')); - const user = req.user; - let res; - // For security, we no longer show the QR code after is verified - // if (user.mfaEnabled) return res.status(404).end(); +// const user = req.user; +// let res; +// // For security, we no longer show the QR code after is verified +// // if (user.mfaEnabled) return res.status(404).end(); - // if (!user.mfaSecret) { //to do - const buffer = nanoid(14); - // generate unique secret for user - // this secret will be used to check the verification code sent by user - // const buffer = await util.promisify(crypto.randomBytes)(14); - // const buffer = crypto.lib.WordArray.random(32) - user.mfaSecret = encode(buffer).toString('utf8'); - // user.mfaSecret = base32Encoded(buffer, 'RFC4648', { padding: false }); +// // if (!user.mfaSecret) { //to do +// const buffer = nanoid(14); +// // generate unique secret for user +// // this secret will be used to check the verification code sent by user +// // const buffer = await util.promisify(crypto.randomBytes)(14); +// // const buffer = crypto.lib.WordArray.random(32) +// user.mfaSecret = encode(buffer).toString('utf8'); +// // user.mfaSecret = base32Encoded(buffer, 'RFC4648', { padding: false }); - // setUser(user); // to do !! +// // setUser(user); // to do !! - // } +// // } - const issuer = 'Google'; - const algorithm = 'SHA1'; - const digits = '6'; - const period = '30'; - const otpType = 'totp'; - const configUri = `otpauth://${otpType}/${issuer}:${user.username}?algorithm=${algorithm}&digits=${digits}&period=${period}&issuer=${issuer}&secret=${user.mfaSecret}`; +// const issuer = 'Google'; +// const algorithm = 'SHA1'; +// const digits = '6'; +// const period = '30'; +// const otpType = 'totp'; +// const configUri = `otpauth://${otpType}/${issuer}:${user.username}?algorithm=${algorithm}&digits=${digits}&period=${period}&issuer=${issuer}&secret=${user.mfaSecret}`; - // res.setHeader('Content-Type', 'image/png'); - const QRCode = require('qrcode'); - console.log(`before done`); - // QRCode.toFileStream(res, configUri); - // const filePath = 'qrcode.png'; // Specify the file path where the QR code should be saved +// // res.setHeader('Content-Type', 'image/png'); +// const QRCode = require('qrcode'); +// console.log(`before done`); +// // QRCode.toFileStream(res, configUri); +// // const filePath = 'qrcode.png'; // Specify the file path where the QR code should be saved - const qrCodeData = buffer; // Replace with your actual QR code data - const filePath = 'qrcode.png'; // Specify the file path where the QR code should be saved +// const qrCodeData = buffer; // Replace with your actual QR code data +// const filePath = 'qrcode.png'; // Specify the file path where the QR code should be saved - qrcode.toFile(filePath, qrCodeData, (error) => { - if (error) { - console.error(error); - // Handle the error appropriately - return; - } - // QR code image has been generated and saved to the file - // Or, you can create a buffer of the image data directly - }) +// qrcode.toFile(filePath, qrCodeData, (error) => { +// if (error) { +// console.error(error); +// // Handle the error appropriately +// return; +// } +// // QR code image has been generated and saved to the file +// // Or, you can create a buffer of the image data directly +// }) -// qrcode.toFile(filePath, configUri, (error) => { -// if (error) { -// console.error(error); -// // Handle the error appropriately -// return; -// } -// const readableStream = fs.createReadStream(filePath); -// res.data = readableStream; - // Use the readable stream as needed -// }); +// // qrcode.toFile(filePath, configUri, (error) => { +// // if (error) { +// // console.error(error); +// // // Handle the error appropriately +// // return; +// // } +// // const readableStream = fs.createReadStream(filePath); +// // res.data = readableStream; +// // Use the readable stream as needed +// // }); - // qrcode.toFileStream(res, configUri); - console.log(`QRcode done`); - return res; - // return - } \ No newline at end of file +// // qrcode.toFileStream(res, configUri); +// console.log(`QRcode done`); +// return res; +// // return +// } \ No newline at end of file diff --git a/containers/api/src/users/users.service.ts b/containers/api/src/users/users.service.ts index 433cea6f..45a9e1e4 100644 --- a/containers/api/src/users/users.service.ts +++ b/containers/api/src/users/users.service.ts @@ -1,3 +1,15 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* users.service.ts :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: apommier +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/06/17 01:00:07 by apommier #+# #+# */ +/* Updated: 2023/06/17 01:00:08 by apommier ### ########.fr */ +/* */ +/* ************************************************************************** */ + import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; @@ -49,6 +61,20 @@ export class UsersService { return (friends) } + async newInvite(user: User, username: string) { + if (!(await this.findOne(username))) + return (0); + // user.friendRequest = user.friendRequest || []; + // console.log("newInvite") + // console.log(user.friendRequest) + user.friendRequest = user.friendRequest || []; + if (user.friendRequest.find(item => item === username)) + return (1); + user.friendRequest.push(username); + this.save(user); + return (1); + } + async getInvite(username: string) { const user = await this.findOne(username) let friendsTab = user.friendRequest @@ -61,6 +87,11 @@ export class UsersService { return (friends) } + async refuseInvite(user: User, username: string) { + user.friendRequest = user.friendRequest.filter((item) => item !== username); + this.save(user); + } + async getHistory(username: string) { const user = await this.findOne(username); @@ -69,19 +100,35 @@ export class UsersService { console.log(user); console.log(user.children); // or perform any operations with the children return children; - // You can also access specific properties of each child - // children.forEach((child) => { - // console.log(child.id); - // console.log(child.opponent); - // // Access other child properties as needed - // }); } } async addFriend(user: User, username: string) { + if (!(await this.findOne(username))) + return (0); + // user.friendRequest = user.friendRequest || []; user.friends = user.friends || []; + if (user.friends.find(item => item === username)) + { + user.friendRequest = user.friendRequest.filter((item) => item !== username); + this.save(user); + return (1); + } user.friends.push(username); + user.friendRequest = user.friendRequest.filter((item) => item !== username); this.save(user); + return (1); + } + + async addBlocked(user: User, username: string) { + if (!(await this.findOne(username))) + return (0); + user.blocked = user.blocked || []; + if (user.blocked.find(item => item === username)) + return (1); + user.blocked.push(username); + this.save(user); + return (1); } async getRanking() { @@ -91,10 +138,6 @@ export class UsersService { async getPic( username: string) { // const user = await this.findOne(username); let result = await this.userRepository.query("select encode(photo, 'base64') FROM public.\"User\" WHERE username = $1;", [username]); - // console.log(`result= ${result}`) - // console.log(`result= ${result.text}`) - // console.log(`encode= ${result.encode}`) - // console.log(`encode= ${result.string}`) if (result.length > 0) { const encodedPhoto = result[0].encode; console.log(`pic!!! =`) diff --git a/containers/chat/package-lock.json b/containers/chat/package-lock.json index 914abd4d..02a0936d 100644 --- a/containers/chat/package-lock.json +++ b/containers/chat/package-lock.json @@ -15,6 +15,7 @@ "@nestjs/platform-socket.io": "^9.4.0", "@nestjs/websockets": "^9.4.0", "cors": "^2.8.5", + "dotenv": "^16.1.4", "reflect-metadata": "^0.1.13", "rxjs": "^7.2.0", "socket.io-client": "^4.6.1", @@ -3398,6 +3399,17 @@ "node": ">=6.0.0" } }, + "node_modules/dotenv": { + "version": "16.1.4", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.1.4.tgz", + "integrity": "sha512-m55RtE8AsPeJBpOIFKihEmqUcoVncQIwo7x9U8ZwLEZw9ZpXboz2c+rvog+jUaJvVrZ5kBOeYQBX5+8Aa/OZQw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", diff --git a/containers/chat/package.json b/containers/chat/package.json index ccf405b6..e1c3403c 100644 --- a/containers/chat/package.json +++ b/containers/chat/package.json @@ -26,6 +26,7 @@ "@nestjs/platform-socket.io": "^9.4.0", "@nestjs/websockets": "^9.4.0", "cors": "^2.8.5", + "dotenv": "^16.1.4", "reflect-metadata": "^0.1.13", "rxjs": "^7.2.0", "socket.io-client": "^4.6.1", diff --git a/containers/chat/src/main.ts b/containers/chat/src/main.ts index c964f081..b81c8ba7 100644 --- a/containers/chat/src/main.ts +++ b/containers/chat/src/main.ts @@ -3,6 +3,10 @@ import { AppModule } from './app.module'; import * as cors from 'cors'; import { Server } from 'socket.io'; import * as socketio from 'socket.io'; +import * as dotenv from 'dotenv'; + +dotenv.config(); +console.log(process.env); async function bootstrap() { const app = await NestFactory.create(AppModule, { @@ -36,7 +40,7 @@ async function bootstrap() { }); }); - await app.listen(4001); + await app.listen(parseInt(process.env.CHAT_PORT) || 4001); } bootstrap(); diff --git a/containers/pong/package-lock.json b/containers/pong/package-lock.json index 914abd4d..02a0936d 100644 --- a/containers/pong/package-lock.json +++ b/containers/pong/package-lock.json @@ -15,6 +15,7 @@ "@nestjs/platform-socket.io": "^9.4.0", "@nestjs/websockets": "^9.4.0", "cors": "^2.8.5", + "dotenv": "^16.1.4", "reflect-metadata": "^0.1.13", "rxjs": "^7.2.0", "socket.io-client": "^4.6.1", @@ -3398,6 +3399,17 @@ "node": ">=6.0.0" } }, + "node_modules/dotenv": { + "version": "16.1.4", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.1.4.tgz", + "integrity": "sha512-m55RtE8AsPeJBpOIFKihEmqUcoVncQIwo7x9U8ZwLEZw9ZpXboz2c+rvog+jUaJvVrZ5kBOeYQBX5+8Aa/OZQw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", diff --git a/containers/pong/package.json b/containers/pong/package.json index ccf405b6..e1c3403c 100644 --- a/containers/pong/package.json +++ b/containers/pong/package.json @@ -26,6 +26,7 @@ "@nestjs/platform-socket.io": "^9.4.0", "@nestjs/websockets": "^9.4.0", "cors": "^2.8.5", + "dotenv": "^16.1.4", "reflect-metadata": "^0.1.13", "rxjs": "^7.2.0", "socket.io-client": "^4.6.1", diff --git a/containers/pong/src/main.ts b/containers/pong/src/main.ts index 7d85a5af..676fb1ff 100644 --- a/containers/pong/src/main.ts +++ b/containers/pong/src/main.ts @@ -21,6 +21,10 @@ import { AppModule } from './app.module'; import * as cors from 'cors'; import { Server } from 'socket.io'; import * as socketio from 'socket.io'; +import * as dotenv from 'dotenv'; + +dotenv.config(); +console.log(process.env); async function bootstrap() { const app = await NestFactory.create(AppModule, { @@ -54,7 +58,7 @@ async function bootstrap() { }); }); - await app.listen(4000); + await app.listen(process.env.PONG_PORT || 4000); } bootstrap(); \ No newline at end of file diff --git a/containers/pong/src/pong/pong.gateway.ts b/containers/pong/src/pong/pong.gateway.ts index 19b81f12..de0e259b 100644 --- a/containers/pong/src/pong/pong.gateway.ts +++ b/containers/pong/src/pong/pong.gateway.ts @@ -68,11 +68,19 @@ export class PongGateway implements OnGatewayInit, OnGatewayConnection, OnGatewa // } // // console.log(`from: ${client.id}`); // } + @SubscribeMessage('pong:invite') + createPrivateGame(client: Socket, payload: any): void { + //after invite accepted ? + //set the two user in a game ? + + } + @SubscribeMessage('pong:matchmaking') addMatchmaking(client: Socket, payload: any): void { console.log("matchmaking"); console.log(payload); + console.log(`option= ${payload.option}`); // Add the client to the waitingClients set along with their chosen option this.waitingClients.add({ client, option: payload.option }); console.log("Adding client to waiting list..."); @@ -147,6 +155,21 @@ addMatchmaking(client: Socket, payload: any): void { // console.log("END OF HANDLE"); // } + @SubscribeMessage('pong:power') + sendPower(client: Socket, payload: any): void + { + console.log(`from: ${client.id}`); + console.log(payload); + + const game = this.games.get(payload.gameId); + const playersIds = game.map(socket => socket.id); + if (playersIds[0] === payload.id) + this.clients[playersIds[1]].emit('pong:power', payload); + else if (playersIds[1] === payload.id) + this.clients[playersIds[0]].emit('pong:power', payload); + console.log("END OF HANDLE"); + } + @SubscribeMessage('pong:message') handleMessage(client: Socket, payload: any): void { diff --git a/containers/react/.env b/containers/react/.env new file mode 100644 index 00000000..3b0e2b83 --- /dev/null +++ b/containers/react/.env @@ -0,0 +1,2 @@ +REACT_APP_BASE_URL=localhost +# REACT_APP_BASE_URL=192.168.1.19 \ No newline at end of file diff --git a/containers/react/src/components/404.tsx b/containers/react/src/components/404.tsx new file mode 100644 index 00000000..9f50336c --- /dev/null +++ b/containers/react/src/components/404.tsx @@ -0,0 +1,23 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* 404.tsx :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: apommier +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/06/18 12:06:43 by apommier #+# #+# */ +/* Updated: 2023/06/18 12:06:58 by apommier ### ########.fr */ +/* */ +/* ************************************************************************** */ + +import React from "react"; + +function PageNotFound() { + return ( +
+

404 Page not found

+
+ ); +} + +export default PageNotFound \ No newline at end of file diff --git a/containers/react/src/components/Alert/GreenAlert.tsx b/containers/react/src/components/Alert/GreenAlert.tsx index ff7ee12d..9193bcd0 100644 --- a/containers/react/src/components/Alert/GreenAlert.tsx +++ b/containers/react/src/components/Alert/GreenAlert.tsx @@ -31,7 +31,7 @@ function GreenAlert ({handleClose, text}){

{text}

- {setTimeout(handleClose, 3000)} + {setTimeout(handleClose, 1500)} ) } diff --git a/containers/react/src/components/Alert/RedAlert.tsx b/containers/react/src/components/Alert/RedAlert.tsx index 3ead8e8a..51fae963 100644 --- a/containers/react/src/components/Alert/RedAlert.tsx +++ b/containers/react/src/components/Alert/RedAlert.tsx @@ -30,7 +30,7 @@ function RedAlert ({handleClose, text}) {

{text}

- {setTimeout(handleClose, 3000)} + {setTimeout(handleClose, 1500)} ) } diff --git a/containers/react/src/components/App.tsx b/containers/react/src/components/App.tsx index 12d2f719..37d07f0b 100644 --- a/containers/react/src/components/App.tsx +++ b/containers/react/src/components/App.tsx @@ -1,5 +1,5 @@ import React from "react"; -import {Routes, Route} from 'react-router-dom'; +import {Routes, Route, Navigate} from 'react-router-dom'; import HomeLogin from "../pages/Home.js"; import Home from "../pages/Home.tsx"; @@ -14,35 +14,55 @@ import {AnimatePresence} from "framer-motion"; import SuccessToken from '../script/tokenSuccess.tsx' - +import PageNotFound from "../components/404.tsx" import DoubleAuth from "../pages/2fa.tsx"; import Game from "../pages/Game.tsx"; import Social from "./Social/Social.tsx"; import Logout from "./Profile/Logout.tsx"; function AnimatedRoute () { + // const location = useLocation(); const location = useLocation(); + if (!localStorage.getItem('token')) + { + return ( + + + }/> + }/> + + {/* } /> */} + {/* } /> */} + + + ) + } + return ( - }/> - }/> - }/> - }/> + {/* }/> */} + }/> + }/> + }/> + }/> - }/> - }/> + }/> + }/> - }/> + }/> }/> - }/> - }/> + }/> + }/> {/* }/> */} - }/> - }/> - }/> + }/> + }/> + }/> + + } /> + } /> ) diff --git a/containers/react/src/components/Game/PlayButton.tsx b/containers/react/src/components/Game/PlayButton.tsx index 041af86e..04576ec7 100644 --- a/containers/react/src/components/Game/PlayButton.tsx +++ b/containers/react/src/components/Game/PlayButton.tsx @@ -6,10 +6,33 @@ function PlayButton() { const history = useNavigate(); + // const handleButtonClick = () => { + // let path = `play`; + // history(path); + // }; const handleButtonClick = () => { - let path = `play`; + let path = `play?`; + + const superpowerCheckbox = document.querySelector('input[value="superpower"]'); + if (superpowerCheckbox.checked) { + path += 'superpower=true&'; + } + + const obstacleCheckbox = document.querySelector('input[value="obstacle"]'); + if (obstacleCheckbox.checked) { + path += 'obstacle=true&'; + } + + const speedCheckbox = document.querySelector('input[value="speed"]'); + if (speedCheckbox.checked) { + path += 'speed=true&'; + } + + // Remove the trailing '&' character + path = path.slice(0, -1); + console.log(path) history(path); - }; + }; return (
diff --git a/containers/react/src/components/Header.tsx b/containers/react/src/components/Header.tsx index c4b61346..799d1abf 100644 --- a/containers/react/src/components/Header.tsx +++ b/containers/react/src/components/Header.tsx @@ -1,13 +1,9 @@ import React, {useState, useEffect} from 'react'; import {AiOutlineMenuUnfold} from 'react-icons/ai'; -// import * as AiIcons from 'react-icons/ai'; import {Link} from 'react-router-dom'; -// import { SidebarData } from './Sidebar/SidebarData'; import DefaultPicture from '../assets/profile.jpg' import { motion, AnimatePresence } from 'framer-motion' import Modal from './Sidebar/Modal.tsx'; -// import {BiLogOutCircle} from 'react-icons/bi'; -// import AnimatePresence from import '../styles/Header.css'; import api from '../script/axiosApi.tsx'; @@ -32,8 +28,8 @@ function Header() { console.error('Error fetching profile picture:', error); } }; - - fetchProfilePicture(); + if (localStorage.getItem('token')) + fetchProfilePicture(); }, []); // console.log(`profile pic= ${profilePicture}`) diff --git a/containers/react/src/components/Messages/Chats.tsx b/containers/react/src/components/Messages/Chats.tsx index 44e9713c..b35450cd 100644 --- a/containers/react/src/components/Messages/Chats.tsx +++ b/containers/react/src/components/Messages/Chats.tsx @@ -20,7 +20,7 @@ import { RiListSettingsLine } from 'react-icons/ri' import { Rank } from "../../DataBase/DataRank"; import GreenAlert from "../Alert/GreenAlert.tsx"; import RedAlert from "../Alert/RedAlert.tsx"; -import YellowAlert from "../Alert/YellowAlert.tsx"; +import YellowAlert from "../Alert/YellowAlert"; import ModalSetting from "./ModalSetting.tsx"; @@ -77,19 +77,14 @@ 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(""); const socket = useRef(); - // Socket handler - // socket.on('message', (data) => { //data should be a message ? - // console.log(`message received data= ${data}`) - // setMessage([...messages, data]); - // }); - - //End of socket handler useEffect(()=> { @@ -100,19 +95,9 @@ function Chats(){ 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"); + socket.current = io('http://' + process.env.REACT_APP_BASE_URL + ':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}`) @@ -132,30 +117,32 @@ 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(()=> { - - // const getConv = async ()=>{ - // try{ - // const convs = await api.get("/conv") - // const tmpUser = await api.get("/profile") - // console.log(convs); - // setUser(tmpUser); - // setConversation(convs.data); - // } - // catch(err){ - // console.log(err); - // } - // }; - // getConv(); - // }, []) - useEffect(()=> { const getMessage = async ()=> { @@ -183,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; @@ -226,41 +217,79 @@ function Chats(){ } } + + const [friend, setFriend] = useState(""); const [modalOpen, setModalOpen] = useState(false); const [addFriend, setAddFriend] = useState(false); const [block, setBlock] = useState(false); + + const [showAddFriendAlert, setShowAddFriendAlert] = useState(false); + const [showBlockAlert, setShowBlockAlert] = useState(false); + const [setting, setSetting] = useState(false); const close = () => setModalOpen(false); const open = () => setModalOpen(true); - const closeAddFriend = () => setAddFriend(false); - const closeBlock = () => setBlock(false); + // const closeAddFriend = () => setAddFriend(false); + // const closeBlock = () => setBlock(false); const closeSetting = () => setSetting(false); - const handleFriend = e => { - setFriend(e.target.value) - }; + // const closeAddFriend = () => setAddFriend(false); + // const closeBlock = () => setBlock(false); - // const findValue = () => { - // // setFind(false); - // console.log(friend); - // Rank.map((tab) => { - // if (tab.name === friend) - // { - // console.log("ok bon"); - // setFind(true); - // } - // }) - // console.log(find); - // // if (!find) - // }; + + const handleFriend = (event) => { + setFriend(event.target.value); + }; - // console.log(`data user1= ${user.username}`) - - // while (user === null) - // ; - + const handleAddFriend = async () => { + try{ + const res = await api.post("/invite", {username: friend}) + // if (res.data === 1) + // console.log("res in friend= ", res) + console.log("res in friend= ", res.data) + if(res.data === 1) + { + setAddFriend(true); + setBlock(false); // Reset block state + setShowBlockAlert(false); + } + else + setAddFriend(false); + setShowAddFriendAlert(true); + } catch(err) { + console.log(err) + } + }; + + const handleBlockFriend = async () => { + try{ + const res = await api.post("/block", {username: friend}) + // if(1) + if (res.data === 1) + { + setBlock(true); + setAddFriend(false); // Reset addFriend state + setShowAddFriendAlert(false); + } + else + setBlock(false); + setShowBlockAlert(true); + } catch(err) { + console.log(err) + } + }; + + const closeAddFriend = () => { + setAddFriend(false); + setShowAddFriendAlert(false); + }; + + const closeBlock = () => { + setBlock(false); + setShowBlockAlert(false); + }; //======================================================================================================== //======================================================================================================== @@ -271,19 +300,6 @@ function Chats(){ return (
- {/*
- profile - - {isLoading ? ( -

Loading...

- ) : ( -

{user.nickname}

- //

{user.username}

- )} -
-
*/} - -
profile @@ -294,13 +310,12 @@ function Chats(){

{user.nickname}

)} -
+ {/*
(addFriend ? setAddFriend(false) : setAddFriend(true))}> - {/* {console.log("find = ",find) && setFind(true)} */} {addFriend && } - {/* {console.log("find2 = ", find) && find && } */} null} > - {setting && } + {setting && } ):("")} -
+
*/} + +
+ + + + + + null}> + {showAddFriendAlert && addFriend && ( + + )} + {showAddFriendAlert && !addFriend && ( + + )} + + + + + + + null}> + {showBlockAlert && block && ( + + )} + {showBlockAlert && !block && ( + + )} + + + {currentChat && isAdmin ? ( + + (setting ? setSetting(false) : setSetting(true))} + > + + null} + > + {setting && } + + + + ):("")} +
+ +
diff --git a/containers/react/src/components/Messages/Message.tsx b/containers/react/src/components/Messages/Message.tsx index 84208d2a..97d73e20 100644 --- a/containers/react/src/components/Messages/Message.tsx +++ b/containers/react/src/components/Messages/Message.tsx @@ -6,7 +6,7 @@ /* By: apommier +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/06/01 18:24:46 by apommier #+# #+# */ -/* Updated: 2023/06/09 09:00:06 by apommier ### ########.fr */ +/* Updated: 2023/06/12 17:05:08 by apommier ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/containers/react/src/components/Messages/Modal.tsx b/containers/react/src/components/Messages/Modal.tsx index 83010b98..50c5e39f 100644 --- a/containers/react/src/components/Messages/Modal.tsx +++ b/containers/react/src/components/Messages/Modal.tsx @@ -1,10 +1,12 @@ import { motion } from "framer-motion"; import Backdrop from "../Sidebar/Backdrop.tsx"; -import { Rank } from "../../DataBase/DataRank" +// import { Rank } from "../../DataBase/DataRank" import '../../styles/Messages.css' -import { useState } from "react"; +import { useState, useEffect } from "react"; import { GrAdd } from "react-icons/gr"; import { Link } from "react-router-dom"; +import api from "../../script/axiosApi.tsx"; +import React from "react"; const dropIn = { hidden:{y:"-100vh", @@ -22,12 +24,37 @@ const dropIn = { }; -const Modal = ({handleClose, text}) => { - const [multi, setMulti] = useState(false); +const Modal = ({handleClose}) => { + // const [multi, setMulti] = useState(false); 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) + } + } + getConv(); + }, []); const handleOptionChange = (selectId, selectedOption) => { + console.log("selected Option=", selectedOption) setSelectTag((prevTags) => prevTags.map((tag) => tag.id === selectId ? { ...tag, selectedOption } : tag @@ -38,13 +65,38 @@ const Modal = ({handleClose, text}) => { const addNewSelectedTag = () => { const newSelectedId = Math.max (...selectTags.map((tag) => tag.id)) + 1; setSelectTag([...selectTags, { id: newSelectedId, selectedOption: ''}]); + 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); + const selectedOptions = selectTags.map((tag) => tag.selectedOption).filter((option) => option !== ''); + + console.log("selected= ", selectedOptions); + //do db stuff here + const data = { + members: selectedOptions, + } + try{ + api.post("/conv", data); + handleClose(); + } catch(err) { + console.log(err); + } setSelectedOptionArray(selectedOptions); + } - let new_name; + // let new_name; + return ( { animate="visible" exit="exit" > -

New Convewrstion

+ {/*

New Conversation

*/} -{/* First selection */} + {selectTags.map((selectTag) => ( +
+ +
+ ))} +
+ +
+
+ Submit + + Cancel +
- -{/* Second selection */} - {selectTags.map((selectTag) =>( -
- -
- )) - } -
-

Selected Option:

-
    - {selectedOptionArray.map((option, index) => ( -
  • {option}
  • - ))} -
-
-
- {multi === true ? ( - ) : " "} -
-
- Submit - - Cancel -
+ {convs.length > 0 && ( + + )} + +
+ Join +
+ + + {/* {selectTags.map((selectTag) => ( +
+ +
+ ))} */} + + + + {/*
+ +
*/} +
diff --git a/containers/react/src/components/Messages/ModalSetting.tsx b/containers/react/src/components/Messages/ModalSetting.tsx index 0ea44d24..cdb83cd1 100644 --- a/containers/react/src/components/Messages/ModalSetting.tsx +++ b/containers/react/src/components/Messages/ModalSetting.tsx @@ -2,9 +2,11 @@ import { motion } from "framer-motion"; import Backdrop from "../Sidebar/Backdrop.tsx"; import { Rank } from "../../DataBase/DataRank" import '../../styles/Messages.css' -import { useState } from "react"; +import { useState, useEffect } from "react"; import { GrAdd } from "react-icons/gr"; import { Link } from "react-router-dom"; +import api from "../../script/axiosApi.tsx"; + const dropIn = { hidden:{y:"-100vh", @@ -22,34 +24,130 @@ const dropIn = { }; -const ModalSetting = ({handleClose, text}) => { +const ModalSetting = ({handleClose, convId}) => { const [password, setPassword] = useState(false); + const [users, setUsers] = useState([]); + const [selectTags, setSelectTag] = useState([{ id: 1, selectedOption: ''}]); + const [selectedUser, setSelectedUser] = useState([]); + const [newName, setNewName] = useState(""); + const [newPassword, setNewPassword] = useState(""); + + useEffect(()=> { + + console.log("convid =", convId) + const getUsers = async ()=>{ + try { + const tmpUsers = await api.get("/users"); + console.log("users=", tmpUsers.data); + setUsers(tmpUsers.data); + } catch(err){ + console.log(err) + } + } + getUsers(); + }, []); + + // const [multi, setMulti] = useState(false); + // const [selectedOptionArray, setSelectedOptionArray] = useState([]); - const handleCheckpass = (e) => { - setPassword(e.target.checked); - } - const [multi, setMulti] = useState(false); - const [selectTags, setSelectTag] = useState([{ id: 1, selectedOption: ''}]); - const [selectedOptionArray, setSelectedOptionArray] = useState([]); const handleOptionChange = (selectId, selectedOption) => { + console.log("tag= ", selectTags) + console.log("option= ", selectedOption) setSelectTag((prevTags) => - prevTags.map((tag) => - tag.id === selectId ? { ...tag, selectedOption } : tag - ) + prevTags.map((tag) => + tag.id === selectId ? { ...tag, selectedOption } : tag + ) ); + setSelectedUser(selectedOption) }; - const addNewSelectedTag = () => { - const newSelectedId = Math.max (...selectTags.map((tag) => tag.id)) + 1; - setSelectTag([...selectTags, { id: newSelectedId, selectedOption: ''}]); - }; + const handleCheckPass = (e) => { + setPassword(e.target.checked); + console.log("password??", e.target.checked) + } + + const handleCheckPriv = (e) => { + // setPassword(e.target.checked); + if (e.target.checked) + { + console.log("chack true", e.target.checked) + try{ + api.post("/private", {convId: convId}) + } catch(err) { + console.log(err); + } + } + else + { + console.log("chack false", e.target.checked) + try{ + api.post("/private", {convId: convId}) + } catch(err) { + console.log(err); + } + } + } + + const handleName = async (e)=>{ + if (e.key !== "Enter") + return ; + try{ + api.post("/name", {convId: convId, name: newName}) + } catch(err) { + console.log(err); + } + handleClose(); + } + + const handlePassword = async (e)=>{ + if (e.key !== "Enter") + return ; + try{ + api.post("/password", {convId: convId, password: newPassword}) + } catch(err) { + console.log(err); + } + handleClose(); + } + + const handleBan = () => { + // console.log("ban option= ", selectedUser) + try{ + api.post("/ban", {convId: convId, username: selectedUser}) + } catch(err) { + console.log(err); + } + handleClose(); + }; + + const handleAdmin = () => { + try{ + api.post("/admin", {convId: convId, username: selectedUser}) + } catch(err) { + console.log(err); + } + handleClose(); + }; + + const handleMute = () => { + try{ + api.post("/mute", {convId: convId, username: selectedUser}) + } catch(err) { + console.log(err); + } + handleClose(); + }; + + const handleInvite = () => { + try{ + api.post("/invite", {convId: convId, username: selectedUser}) + } catch(err) { + console.log(err); + } + handleClose(); + }; - const saveSelectedOptions = () => { - const selectedOptions = selectTags.map((tag) => tag.selectedOption); - setSelectedOptionArray(selectedOptions); - } - let new_name; return ( { animate="visible" exit="exit" > - {/*

New Convewrstion

*/} {/* First selection */}
-

Private

-

PassW

- {password ? ():("")} +

Private

+

Password

+ + + {password ? ( + setNewPassword(e.target.value)} + onKeyDown={handlePassword} + type="text" + className="in" + placeholder="Password"/> + ): + ("")} + +
- + setNewName(e.target.value)} + onKeyDown={handleName} + type="text" + className="in" + placeholder="New Name" + />
- {/* */} - {/* Second selection */}
- Send - {selectTags.map((selectTag) =>( -
- -
- )) - } + {selectTags.map((selectTag) => ( +
+ +
+ ))} + +
- Ban - Mute - Admin + Send + Ban + Mute + Admin
- {/* {selectTags.map((selectTag) =>( -
- - -
- )) - } -
-

Selected Option:

-
    - {selectedOptionArray.map((option, index) => ( -
  • {option}
  • - ))} -
-
-
- {multi === true ? ( - ) : " "} -
-
- Submit - - Cancel -
*/}
diff --git a/containers/react/src/components/Profile/EditName.tsx b/containers/react/src/components/Profile/EditName.tsx index c8b74e85..be339f14 100644 --- a/containers/react/src/components/Profile/EditName.tsx +++ b/containers/react/src/components/Profile/EditName.tsx @@ -6,6 +6,7 @@ import {useState} from 'react'; import "../../styles/Profile.css" import api from '../../script/axiosApi.tsx'; +import React from "react"; const dropIn = { hidden: { @@ -58,7 +59,7 @@ const ModalEdit = ( handleClose ) => {
{UserProfile.UserName = nickname;}}> - change + change
diff --git a/containers/react/src/components/Profile/Logout.tsx b/containers/react/src/components/Profile/Logout.tsx index dd422844..029078d5 100644 --- a/containers/react/src/components/Profile/Logout.tsx +++ b/containers/react/src/components/Profile/Logout.tsx @@ -4,7 +4,7 @@ function Logout(){ localStorage.clear(); - const path = `http://localhost/`; + const path = 'http://' + process.env.REACT_APP_BASE_URL + '/'; // history(path, { replace: true }); // window.location.replace(path); // window.history.pushState({}, '', path); diff --git a/containers/react/src/components/Social/Friend.tsx b/containers/react/src/components/Social/Friend.tsx index 4feae2e5..b0892b90 100644 --- a/containers/react/src/components/Social/Friend.tsx +++ b/containers/react/src/components/Social/Friend.tsx @@ -1,12 +1,12 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* Friend.jsx :+: :+: :+: */ +/* Friend.tsx :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: apommier +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/06/09 08:18:58 by apommier #+# #+# */ -/* Updated: 2023/06/09 08:35:21 by apommier ### ########.fr */ +/* Updated: 2023/06/18 13:12:26 by apommier ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,6 +17,7 @@ import styled from "styled-components"; import { RxCircle } from "react-icons/rx"; import { CgFontSpacing } from "react-icons/cg"; +import React from "react"; const UserChat = styled.div ` padding: 5px; @@ -79,7 +80,8 @@ export default function Friend({currentUser}) }; const handleButtonClick = (user) => { - let path = `http://localhost/profile/${user.username}`; + let path = `http://` + process.env.REACT_APP_BASE_URL + `/profile/${user.username}`; + console.log("path= ", path) // history(path, { replace: true }); // window.location.replace(path); window.history.pushState({}, null, path); diff --git a/containers/react/src/components/Social/Friend.tsx~HEAD b/containers/react/src/components/Social/Friend.tsx~HEAD new file mode 100644 index 00000000..0c6c894d --- /dev/null +++ b/containers/react/src/components/Social/Friend.tsx~HEAD @@ -0,0 +1,111 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* Friend.jsx :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: apommier +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/06/09 08:18:58 by apommier #+# #+# */ +/* Updated: 2023/06/15 19:05:14 by apommier ### ########.fr */ +/* */ +/* ************************************************************************** */ + +import { useEffect, useState } from "react"; +import api from '../../script/axiosApi.tsx'; +import DefaultPicture from '../../assets/profile.jpg' +import styled from "styled-components"; + +import { RxCircle } from "react-icons/rx"; +import { CgFontSpacing } from "react-icons/cg"; + +const UserChat = styled.div ` + padding: 5px; + display: flex; + align-items: center; + gap: 5px; + color: white; + cursor: pointer; + + &:hover{ + background-color: #3e3c61; + } +` + +const SideP = styled.p` + font-size: 14px; + color: lightgray; + margin-left: 15px; +` + +export default function Friend({currentUser}) +{ + const [profilePicture, setProfilePicture] = useState(''); + + useEffect(() => { + const fetchProfilePicture = async () => { + try { + // const user = await api.get("/profile"); + const pic = await api.post("/getPicture", {username: currentUser.username}) + // console.log(`user naem profile pic222= ${currentUser.username}`) + // console.log(` profile pic222= ${pic.data}`) + setProfilePicture(pic.data); + } catch (error) { + console.error('Error fetching profile picture:', error); + } + }; + + fetchProfilePicture(); + }) + + function getStatus(friend) + { + let status = friend.status + console.log(`status= ${status}`) + let statusColor; + + if (status === 0) + statusColor = 'grey'; + else if (status === 1) + statusColor = 'green'; + else if (status === 2) + statusColor = 'blue'; + return statusColor; + } + + const handleSpectate = (user) => { + //socket connection and add to party with one with username + console.log(`spectate hehe`) + console.log(`user= ${user}`) + }; + + const handleButtonClick = (user) => { + let path = `http://` + process.env.REACT_APP_BASE_URL + `/profile/${user.username}`; + console.log("path= ", path) + // history(path, { replace: true }); + // window.location.replace(path); + window.history.pushState({}, null, path); + window.location.reload(false); + }; + + return ( + + {profilePicture ? ( + + ) : ( + Default Profile Picture + )} +
+ handleButtonClick(currentUser)}>{currentUser.nickname} + + + {getStatus(currentUser) !== 'blue' ? ( + <> + ) : ( + + )} +
+
+ ) +} + + diff --git a/containers/react/src/components/Social/FriendRequest.tsx b/containers/react/src/components/Social/FriendRequest.tsx index 3b982f32..4fffff6e 100644 --- a/containers/react/src/components/Social/FriendRequest.tsx +++ b/containers/react/src/components/Social/FriendRequest.tsx @@ -28,14 +28,18 @@ const SideP = styled.p` export default function Friend({currentUser}) { const [profilePicture, setProfilePicture] = useState(''); - const [request, setRequest] = useState(''); + const [request, setRequest] = useState(''); //user who invite + const [clickEvent, setClickEvent] = useState(false); + // const [user, setUser] = useState(null); useEffect(() => { const fetchProfilePicture = async () => { try { - // const user = await api.get("/profile"); + // const user = await api.get("/profile");\ + // const tmpUser = await api.get("/profile") const pic = await api.post("/getPicture", {username: currentUser.username}) const tmpRequest = await api.post("/user", {username: currentUser.username}) + // setUser(tmpUser.data); setRequest(tmpRequest.data); // console.log(`user naem profile pic222= ${currentUser.username}`) // console.log(` profile pic222= ${pic.data}`) @@ -46,45 +50,43 @@ export default function Friend({currentUser}) }; fetchProfilePicture(); - }) - - function getStatus(friend) - { - let status = friend.status - console.log(`status= ${status}`) - let statusColor; - - if (status === 0) - statusColor = 'grey'; - else if (status === 1) - statusColor = 'green'; - else if (status === 2) - statusColor = 'blue'; - return statusColor; - } - - const handleSpectate = (user) => { - //socket connection and add to party with one with username - console.log(`spectate hehe`) - console.log(`user= ${user}`) - }; + }, [clickEvent]) const handleButtonClick = (user) => { - let path = `http://localhost/profile/${user.username}`; + let path = `http://` + process.env.REACT_APP_BASE_URL + `/profile/${user.username}`; // history(path, { replace: true }); // window.location.replace(path); window.history.pushState({}, null, path); window.location.reload(false); }; - const Accept = (user) => { + const Accept = async (request) => { + try{ + await api.post("/friend", {username: request.username}) + setClickEvent(true); + } catch(err) { + console.log(err); + } console.log("accept") + console.log(`request = ${request}`) } - const Refuse = (user) => { + const Refuse = async (request) => { + try{ + await api.post("/refuseInvite", {username: request.username}) + setClickEvent(true); + } catch(err) { + console.log(err); + } console.log("refuse") + console.log(`request = ${request}`) } + // Vérifier si le contenu doit être caché + if (clickEvent) { + return null; // Rendre null pour ne pas afficher le contenu + } + return ( {profilePicture ? ( diff --git a/containers/react/src/components/Social/FriendRequest.tsx~HEAD b/containers/react/src/components/Social/FriendRequest.tsx~HEAD new file mode 100644 index 00000000..4fffff6e --- /dev/null +++ b/containers/react/src/components/Social/FriendRequest.tsx~HEAD @@ -0,0 +1,106 @@ + +import { useEffect, useState } from "react"; +import api from '../../script/axiosApi.tsx'; +import DefaultPicture from '../../assets/profile.jpg' +import styled from "styled-components"; + +import { RxCheckCircled, RxCircleBackslash } from "react-icons/rx"; + +const UserChat = styled.div ` + padding: 5px; + display: flex; + align-items: center; + gap: 5px; + color: white; + cursor: pointer; + + &:hover{ + background-color: #3e3c61; + } +` + +const SideP = styled.p` + font-size: 14px; + color: lightgray; + margin-left: 15px; +` + +export default function Friend({currentUser}) +{ + const [profilePicture, setProfilePicture] = useState(''); + const [request, setRequest] = useState(''); //user who invite + const [clickEvent, setClickEvent] = useState(false); + // const [user, setUser] = useState(null); + + useEffect(() => { + const fetchProfilePicture = async () => { + try { + // const user = await api.get("/profile");\ + // const tmpUser = await api.get("/profile") + const pic = await api.post("/getPicture", {username: currentUser.username}) + const tmpRequest = await api.post("/user", {username: currentUser.username}) + // setUser(tmpUser.data); + setRequest(tmpRequest.data); + // console.log(`user naem profile pic222= ${currentUser.username}`) + // console.log(` profile pic222= ${pic.data}`) + setProfilePicture(pic.data); + } catch (error) { + console.error('Error fetching profile picture:', error); + } + }; + + fetchProfilePicture(); + }, [clickEvent]) + + const handleButtonClick = (user) => { + let path = `http://` + process.env.REACT_APP_BASE_URL + `/profile/${user.username}`; + // history(path, { replace: true }); + // window.location.replace(path); + window.history.pushState({}, null, path); + window.location.reload(false); + }; + + const Accept = async (request) => { + try{ + await api.post("/friend", {username: request.username}) + setClickEvent(true); + } catch(err) { + console.log(err); + } + console.log("accept") + console.log(`request = ${request}`) + } + + const Refuse = async (request) => { + try{ + await api.post("/refuseInvite", {username: request.username}) + setClickEvent(true); + } catch(err) { + console.log(err); + } + console.log("refuse") + console.log(`request = ${request}`) + } + + // Vérifier si le contenu doit être caché + if (clickEvent) { + return null; // Rendre null pour ne pas afficher le contenu + } + + return ( + + {profilePicture ? ( + + ) : ( + Default Profile Picture + )} +
+ handleButtonClick(currentUser)}>{currentUser.nickname} + Accept(request)} color={'green'}/> + Refuse(request)} color={'red'}/> + +
+
+ ) +} + \ No newline at end of file diff --git a/containers/react/src/components/Social/Social.tsx b/containers/react/src/components/Social/Social.tsx index b5916b43..f6aefd5e 100644 --- a/containers/react/src/components/Social/Social.tsx +++ b/containers/react/src/components/Social/Social.tsx @@ -42,9 +42,9 @@ function Social (){ const getFriend = async ()=>{ try{ - const tmpFriends = await api.get("/friends") + const tmpFriends = await api.get("/friends") const tmpUser = await api.get("/profile") - const tmpInv = await api.get("/invite") + const tmpInv = await api.get("/inviteRequest") const pic = await api.post("/getPicture", {username: tmpUser.data.username}) setInvite(tmpInv.data); diff --git a/containers/react/src/pages/Field.tsx b/containers/react/src/pages/Field.tsx index bb1f8009..a8505d82 100644 --- a/containers/react/src/pages/Field.tsx +++ b/containers/react/src/pages/Field.tsx @@ -1,13 +1,48 @@ -import { useEffect } from 'react'; +import { useEffect, useLocation } from 'react'; // import { useState, useRef } from 'react'; -import { drawCanvas } from './canvas.tsx'; +import DrawCanvas from './canvas.tsx'; +import queryString from 'query-string'; import '../styles/field.css'; +import { useParams } from "react-router-dom"; + +// import { withRouter } from 'react-router-dom'; + function Field() { useEffect(() => { + // const location = useLocation(); + const queryParams = queryString.parse(window.location.search); + console.log("launch canva hehe") - drawCanvas(); + let Modifiers = 0; + + if (queryParams.superpower === 'true') { + Modifiers += 1; + } + + if (queryParams.obstacle === 'true') { + Modifiers += 2; + } + + if (queryParams.speed === 'true') { + Modifiers += 4; + } + // console.log(`modifiers= ${Modifiers}`) + // DrawCanvas(Modifiers); + // return () => { + // console.log("000000000000000000000000000000000") + // // socketRef.current.disconnect(); + // }; + + // console.log(`modifiers= ${Modifiers}`) + const cleanup = DrawCanvas(Modifiers); + + return () => { + console.log("Cleanup"); + cleanup(); // Call the cleanup function to stop the ongoing process or perform necessary cleanup tasks + }; + }, []); // const [buttonClicked, setButtonClicked] = useState(false); @@ -28,6 +63,7 @@ function Field() } export default Field; +// export default withRouter(Field); // function Field() { diff --git a/containers/react/src/pages/Home.js b/containers/react/src/pages/Home.js index 8331debb..b848c466 100644 --- a/containers/react/src/pages/Home.js +++ b/containers/react/src/pages/Home.js @@ -26,7 +26,8 @@ function HomeLogin() return ; } // else - let path = "https://api.intra.42.fr/oauth/authorize?client_id=u-s4t2ud-6d29dfa49ba7146577ffd8bf595ae8d9e5aaa3e0a9615df18777171ebf836a41&redirect_uri=http%3A%2F%2Flocalhost%3A80%2Fapi%2Fauth%2Flogin&response_type=code"; + // let path = "https://api.intra.42.fr/oauth/authorize?client_id=u-s4t2ud-6d29dfa49ba7146577ffd8bf595ae8d9e5aaa3e0a9615df18777171ebf836a41&redirect_uri=http%3A%2F%2F" + process.env.REACT_APP_BASE_URL + "%3A80%2Fapi%2Fauth%2Flogin&response_type=code"; + let path = "https://api.intra.42.fr/oauth/authorize?client_id=u-s4t2ud-6d29dfa49ba7146577ffd8bf595ae8d9e5aaa3e0a9615df18777171ebf836a41&redirect_uri=http%3A%2F%2F" + process.env.REACT_APP_BASE_URL + "%2Fapi%2Fauth%2Flogin&response_type=code" window.location.replace(path); }; diff --git a/containers/react/src/pages/canvas.tsx b/containers/react/src/pages/canvas.tsx index 126079a0..857d582d 100644 --- a/containers/react/src/pages/canvas.tsx +++ b/containers/react/src/pages/canvas.tsx @@ -2,19 +2,44 @@ import api from '../script/axiosApi.tsx'; -// import { useEffect } from 'react'; +// import { useEffect, useRef } from 'react'; import io from 'socket.io-client'; // const socket = io('http://192.168.1.14:4000'); // const socket = io('http://86.209.110.20:4000'); // const socket = io('http://172.29.113.91:4000'); -export function drawCanvas() { - const socket = io('http://localhost:4000'); - // const socket = io() +function DrawCanvas(option) { + + + + console.log(`option= ${option}`); + const superpowerModifier = option & 1; // Retrieves the superpower modifier + const obstacleModifier = (option >> 1) & 1; // Retrieves the obstacle modifier + const speedModifier = (option >> 2) & 1; // Retrieves the speed modifier + + console.log(`superpowerModifier = ${superpowerModifier}`); + console.log(`obstacleModifier = ${obstacleModifier}`); + console.log(`speedModifier = ${speedModifier}`); + + + + // const socketRef = useRef(null); + // socketRef.current = io('http://localhost:4000'); + const socket = io('http://' + process.env.REACT_APP_BASE_URL + ':4000'); + // const socket = socketRef.current console.log("start function"); const canvas = document.getElementById('myCanvas'); const ctx = canvas.getContext('2d'); + // useEffect(() => { + // console.log("useeffect?????????????????") + // return () => { + // console.log("000000000000000000000000000000000") + // socketRef.current.disconnect(); + // }; + // }, []); + + //======================================================================================================== //======================================================================================================== // Var Declaration @@ -28,6 +53,7 @@ export function drawCanvas() { let opRank; //general canvas + let running = true; const scale = window.devicePixelRatio; canvas.width = canvas.offsetWidth; // canvas.height = canvas.width * 0.7 @@ -39,8 +65,9 @@ export function drawCanvas() { let paddleY = canvas.height / 2 - (paddleHeight / 2); let paddleX = canvas.width / 40; let paddleSpeed = canvas.height / 40; - + //opponent var + let opPaddleHeight = canvas.height * 0.25; let oPaddleY = paddleY; //mouse and touch @@ -81,6 +108,7 @@ export function drawCanvas() { console.log(`id ion matcj= ${myId}`) const info = { id: myId, + option: option, }; socket.emit('pong:matchmaking', info); } @@ -165,6 +193,27 @@ export function drawCanvas() { vY = data.vY; }); + + socket.on('pong:paddle', (data) => { + console.log("paddle info receive") + oPaddleY = (data.paddleY / data.height) * canvas.height + }); + + socket.on('pong:power', (data) => { + console.log("paddle info receive") + + oPaddleY = 0; + opPaddleHeight = canvas.height; + + setTimeout(() => { + // code à exécuter après 5 secondes + opPaddleHeight = canvas.height * 0.25; + oPaddleY = canvas.height / 2 - paddleHeight / 2; + console.log('Cinq secondes se sont écoulées.'); + }, 5000); + // oPaddleY = (data.paddleY / data.height) * canvas.height + }); + function send_info() { if (gameId === 0) @@ -183,11 +232,6 @@ export function drawCanvas() { socket.emit('pong:message', info); } - socket.on('pong:paddle', (data) => { - console.log("paddle info receive") - oPaddleY = (data.paddleY / data.height) * canvas.height - }); - function send_point() { if (gameId === 0) @@ -229,6 +273,17 @@ export function drawCanvas() { socket.emit('pong:paddle', info); } + function use_power() + { + const info = { + gameId: gameId, + width: canvas.width, + height: canvas.height, + id: myId, + } + socket.emit('pong:power', info); + } + function send_forced_info() { if (gameId === 0) @@ -275,7 +330,7 @@ export function drawCanvas() { function drawPaddle() { ctx.fillStyle = 'white'; ctx.fillRect(paddleX, paddleY, paddleWidth, paddleHeight); - ctx.fillRect(canvas.width - paddleX - paddleWidth, oPaddleY, paddleWidth, paddleHeight); + ctx.fillRect(canvas.width - paddleX - paddleWidth, oPaddleY, paddleWidth, opPaddleHeight); } function drawball() @@ -287,7 +342,7 @@ export function drawCanvas() { ctx.fill(); } - + //======================================================================================================== //======================================================================================================== // Loop @@ -298,9 +353,18 @@ matchmaking(); // while (!gameId) // ; + // Define a function to stop the drawing process + const stopDrawCanvas = () => { + running = false; + // Perform any necessary cleanup tasks + // ... + }; function draw(timestamp) { + console.log("turning"); + if (!running) + return ; if (gameId === 0 ) { requestAnimationFrame(draw); @@ -326,14 +390,14 @@ function draw(timestamp) api.post('/status', {status: 1}); console.log("send loose"); } - window.location.replace("http://localhost/pong"); + window.location.replace("http://" + process.env.REACT_APP_BASE_URL + "/pong"); return ; } const deltaTime = timestamp - lastUpdateTime; lastUpdateTime = timestamp; ballX += vX * deltaTime * canvas.width; - ballY += vY * deltaTime * canvas.width; + ballY += vY * deltaTime * canvas.height; ctx.clearRect(0, 0, canvas.width, canvas.height); drawPaddle(); @@ -343,7 +407,8 @@ function draw(timestamp) is_out(); requestAnimationFrame(draw); } -requestAnimationFrame(draw); + + //======================================================================================================== //======================================================================================================== @@ -360,6 +425,13 @@ requestAnimationFrame(draw); vY = vX * Math.sin(-bounceAngle); if (vX < 0) vX = -vX; + if (speedModifier) + { + if (vX > 0) + vX += 0.0001; + else + vX -= 0.0001; + } } @@ -387,7 +459,12 @@ requestAnimationFrame(draw); } if (ballY - ballRadius - 2 <= 0 || ballY + ballRadius + 2 >= canvas.height) //touch up or down wall { + // if () vY = -vY; + if (ballY > (canvas.height / 2))//down wall + ballY = canvas.height - ballRadius - 2 + else + ballY = ballRadius + 2 // send_info(); } // else if (ballX + ballRadius + 2 >= canvas.width) //touch right wall @@ -416,6 +493,24 @@ requestAnimationFrame(draw); send_point(); // send_forced_info(); } + if (ballX > canvas.width) + { + console.log("win point") + // if (ballY <= paddleY + paddleHeight + ballRadius && ballY >= paddleY - ballRadius) + // { + // console.log('true hehe'); + // ballX = paddleX + paddleWidth + ballRadius; + // updateVector(); + // return ; + // } + // ballX = canvas.width / 2; + // ballY = canvas.height / 2; + // vX = 0; + // vY = 0; + // hisScore += 1; + // send_point(); + // // send_forced_info(); + } } @@ -510,8 +605,11 @@ requestAnimationFrame(draw); } else if (event.code === "KeyR") { + if (!superpowerModifier) + return ; paddleY = 0; paddleHeight = canvas.height; + use_power(); setTimeout(() => { // code à exécuter après 5 secondes paddleHeight = canvas.height * 0.25; @@ -521,4 +619,9 @@ requestAnimationFrame(draw); } }); -} \ No newline at end of file + requestAnimationFrame(draw); + console.log("retuuuuuuuuuuurn") + return (stopDrawCanvas); +} + +export default DrawCanvas \ No newline at end of file diff --git a/containers/react/src/script/axiosApi.tsx b/containers/react/src/script/axiosApi.tsx index 07a89caa..8a9c80b9 100644 --- a/containers/react/src/script/axiosApi.tsx +++ b/containers/react/src/script/axiosApi.tsx @@ -12,8 +12,17 @@ function getToken() { console.log(`getToken = ${getToken()}`) console.log(`Bearer ${localStorage.getItem("token")}`) +const test = "192.168.1.19" +// const url = 'http://' + process.env.REACT_APP_BASE_URL + '/api' +// const url = 'http://' + test + '/api' + +// console.log("url= ", url) +console.log("test= ", test) +console.log("env= ", process.env.REACT_APP_BASE_URL) + let api = axios.create({ - baseURL: 'http://localhost/api', +// baseURL: 'http://localhost/api', +baseURL: 'http://' + process.env.REACT_APP_BASE_URL + '/api', headers: { // Authorization: `Bearer ${getToken()}`, Authorization : `Bearer ${localStorage.getItem("token")}` diff --git a/containers/react/src/script/tokenSuccess.tsx b/containers/react/src/script/tokenSuccess.tsx index 87686fca..503e2118 100644 --- a/containers/react/src/script/tokenSuccess.tsx +++ b/containers/react/src/script/tokenSuccess.tsx @@ -6,8 +6,8 @@ function SuccessToken() { const { data } = queryString.parse(location.search); const cleanData = data.slice(1, -1); localStorage.setItem('token', `${cleanData}`); - console.log(`prout token2= ${localStorage.getItem('token')}`) - window.location.replace("http://localhost/pong"); + console.log(`token= ${localStorage.getItem('token')}`) + window.location.replace("http://" + process.env.REACT_APP_BASE_URL + "/pong"); } export default SuccessToken; \ No newline at end of file diff --git a/containers/react/src/styles/chat.css b/containers/react/src/styles/chat.css index cf81842f..1a5681b2 100644 --- a/containers/react/src/styles/chat.css +++ b/containers/react/src/styles/chat.css @@ -156,4 +156,14 @@ bottom: 50px; font-size: 13px; font-style: italic; -} \ No newline at end of file +} + + +/* Messages.css */ +/* import '../../styles/Messages.css' */ + +/* General styles */ +/* Messages.css */ +/* import '../../styles/Messages.css' */ + +/* General styles \ No newline at end of file diff --git a/containers/test b/containers/test new file mode 100644 index 00000000..f7eced04 --- /dev/null +++ b/containers/test @@ -0,0 +1,2 @@ +cc toi +cc 2 \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 0b3b1242..04b613cb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,14 +8,25 @@ services: env_file: .env depends_on: - api + + # command: sh -c "envsubst < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'" ports: - 80:80 volumes: - - ./conf/nginx.conf:/etc/nginx/conf.d/default.conf + - ./conf/nginx.conf:/etc/nginx/conf.d/default.conf + # volumes: + # - "./conf:/etc/nginx/templates/" + # ports: + # - 80:80 + # volumes: + # - ./conf/nginx.conf:/etc/nginx/conf.d/default.conf + # command: sh -c "envsubst < /etc/nginx/conf.d/default.conf > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'" # - ./containers/frontend:/var/www/html networks: - pongNetwork + + react_app: image: node:latest container_name: react_app @@ -48,6 +59,7 @@ services: entrypoint: ["sh", "-c" , "npm install && npm run start:dev"] postgresql: + env_file: .env image: postgres:14.1-alpine restart: unless-stopped container_name: postgresql