trying tu udate

This commit is contained in:
kinou-p 2023-06-18 13:25:06 +02:00
commit f6d70a03c4
49 changed files with 2133 additions and 549 deletions

37
.env
View File

@ -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
#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

View File

@ -2,15 +2,14 @@ server {
# listen 443 ssl;
# listen 80 ssl;
# listen 443 ssl;
# 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;
}
}

View File

@ -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",

View File

@ -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",

View File

@ -1,3 +1,15 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* app.controller.ts :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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,9 +440,10 @@ 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);
@ -317,6 +451,7 @@ export class AppController {
return await this.chatService.findConv(data.convId);
}
@UseGuards(JwtAuthGuard)
@Post('/getMessage')
async getMessage(@Body() data: any) {
console.log(data);
@ -332,4 +467,73 @@ 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)
}
}

View File

@ -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],

View File

@ -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),
};

View File

@ -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,
};

View File

@ -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);

View File

@ -1,7 +1,14 @@
// import { Injectable } from '@nestjs/common';
// @Injectable()
// export class ConvService {}
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* chat.service.ts :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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<Message>,
) {}
async save(conv: Conv): Promise<Conv> {
return await this.chatRepository.save(conv);
}
async findAll(): Promise<Conv[]> {
return await this.chatRepository.find();
}
async createConv(conv: Conv): Promise<Conv> {
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<Conv[]>{
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()
// 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<Message> {
async createMessage(message: Message, username: string): Promise<Message> {
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);
}
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<Message[]> {
// 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);
}
}

View File

@ -6,7 +6,7 @@
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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

View File

@ -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();

View File

@ -1,3 +1,15 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* chat.entity.ts :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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;

View File

@ -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[];

View File

@ -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;
}
// 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 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 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;
}
// // 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 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;
}
// 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);
// // 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, configUri, (error) => {
// qrcode.toFile(filePath, qrCodeData, (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
// });
// // 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.toFileStream(res, configUri);
console.log(`QRcode done`);
return res;
// return
}
// // qrcode.toFileStream(res, configUri);
// console.log(`QRcode done`);
// return res;
// // return
// }

View File

@ -1,3 +1,15 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* users.service.ts :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 || [];
user.friends.push(username);
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!!! =`)

View File

@ -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",

View File

@ -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",

View File

@ -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();

View File

@ -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",

View File

@ -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",

View File

@ -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();

View File

@ -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
{

2
containers/react/.env Normal file
View File

@ -0,0 +1,2 @@
REACT_APP_BASE_URL=localhost
# REACT_APP_BASE_URL=192.168.1.19

View File

@ -0,0 +1,23 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* 404.tsx :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 (
<div>
<p>404 Page not found</p>
</div>
);
}
export default PageNotFound

View File

@ -31,7 +31,7 @@ function GreenAlert ({handleClose, text}){
<AiOutlineCheckCircle/>
<p>{text}</p>
</motion.div>
{setTimeout(handleClose, 3000)}
{setTimeout(handleClose, 1500)}
</Backdrop>
)
}

View File

@ -30,7 +30,7 @@ function RedAlert ({handleClose, text}) {
<BiErrorCircle/>
<p>{text}</p>
</motion.div>
{setTimeout(handleClose, 3000)}
{setTimeout(handleClose, 1500)}
</Backdrop>
)
}

View File

@ -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 (
<AnimatePresence>
<Routes location={location} key={location.pathname}>
<Route path="/" element={<HomeLogin/>}/>
<Route path="/token" element={<SuccessToken />}/>
{/* <Route path="/404" element={<HomeLogin/>} /> */}
{/* <Route path="*" element={<Navigate to="/404" />} /> */}
</Routes>
</AnimatePresence>
)
}
return (
<AnimatePresence>
<Routes location={location} key={location.pathname}>
<Route exact path="/" element={<HomeLogin/>}/>
<Route exact path="/profile" element={<Home/>}/>
<Route exact path="/profile/:username" element={<Home/>}/>
<Route exact path="/qr" element={<QrCode/>}/>
{/* <Route path="/login" element={<HomeLogin/>}/> */}
<Route path="/" element={<Home/>}/>
<Route path="/profile" element={<Home/>}/>
<Route path="/profile/:username" element={<Home/>}/>
<Route path="/qr" element={<QrCode/>}/>
<Route exact path="/2fa" element={<DoubleAuth/>}/>
<Route exact path="/Social" element={<Social/>}/>
<Route path="/2fa" element={<DoubleAuth/>}/>
<Route path="/Social" element={<Social/>}/>
<Route exact path="/token" element={<SuccessToken />}/>
<Route path="/token" element={<SuccessToken />}/>
<Route path="/game" element={<PlayButton />}/>
<Route exact path="/pong" element={<Game />}/>
<Route exact path="/pong/play" element={<Field />}/>
<Route path="/pong" element={<Game />}/>
<Route path="/pong/play" element={<Field />}/>
{/* <Route path="/profile" element={<PlayButton />}/> */}
<Route exact path="/login42" element={<Login42 />}/>
<Route exact path="/logout" element={<Logout />}/>
<Route exact path="/messages" element={<Messages />}/>
<Route path="/login42" element={<Login42 />}/>
<Route path="/logout" element={<Logout />}/>
<Route path="/messages" element={<Messages />}/>
<Route path="/404" element={<PageNotFound />} />
<Route path="*" element={<Navigate to="/404" />} />
</Routes>
</AnimatePresence>
)

View File

@ -6,8 +6,31 @@ 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);
};

View File

@ -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,7 +28,7 @@ function Header() {
console.error('Error fetching profile picture:', error);
}
};
if (localStorage.getItem('token'))
fetchProfilePicture();
}, []);

View File

@ -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(()=> {
const updateChat = async ()=> {
// if (currentChat)
// console.log(currentChat.id)
if (currentChat)
console.log(currentChat.id)
{
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 handleFriend = (event) => {
setFriend(event.target.value);
};
// 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 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)
}
};
// console.log(`data user1= ${user.username}`)
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)
}
};
// while (user === null)
// ;
const closeAddFriend = () => {
setAddFriend(false);
setShowAddFriendAlert(false);
};
const closeBlock = () => {
setBlock(false);
setShowBlockAlert(false);
};
//========================================================================================================
//========================================================================================================
@ -271,19 +300,6 @@ function Chats(){
return (
<div className="chat">
{/* <div className='navbar'>
<img src={DefaultPic} alt="profile" className="pic"/>
<span>
{isLoading ? (
<h4>Loading...</h4>
) : (
<h4>{user.nickname}</h4>
// <h4>{user.username}</h4>
)}
</span>
</div> */}
<div className='navbar'>
<img src={DefaultPic} alt="profile" className="pic"/>
@ -294,13 +310,12 @@ function Chats(){
<h4>{user.nickname}</h4>
)}
</span>
<div className="end">
{/* <div className="end">
<input className="lookForFriends" type="text" value={friend} onChange={handleFriend}/>
<TouchDiv>
<motion.div
onClick={() => (addFriend ? setAddFriend(false) : setAddFriend(true))}>
<MdOutlineGroupAdd/>
{/* {console.log("find = ",find) && setFind(true)} */}
</motion.div>
<AnimatePresence
initial={false}
@ -308,7 +323,6 @@ function Chats(){
>
{addFriend && <GreenAlert handleClose={closeAddFriend} text={friend + " was successfuly added"}/>}
</AnimatePresence>
{/* {console.log("find2 = ", find) && find && <BasicAlert modalOpen={find} handleClose={setFind(false)}/>} */}
</TouchDiv>
<TouchDiv>
<motion.div
@ -334,12 +348,59 @@ function Chats(){
initial={false}
onExitComplete={() => null}
>
{setting && <ModalSetting handleClose={closeSetting}/>}
{setting && <ModalSetting handleClose={closeSetting} convId={currentChat.id}/>}
</AnimatePresence>
</motion.div>
</TouchDiv>
):("")}
</div> */}
<div className="end">
<input className="lookForFriends" type="text" value={friend} onChange={handleFriend} />
<TouchDiv>
<motion.div onClick={handleAddFriend}>
<MdOutlineGroupAdd />
</motion.div>
<AnimatePresence initial={false} onExitComplete={() => null}>
{showAddFriendAlert && addFriend && (
<GreenAlert handleClose={closeAddFriend} text={ 'invitation sent to ' + friend} />
)}
{showAddFriendAlert && !addFriend && (
<RedAlert handleClose={closeAddFriend} text={friend + ' was not found'} />
)}
</AnimatePresence>
</TouchDiv>
<TouchDiv>
<motion.div onClick={handleBlockFriend}>
<ImBlocked />
</motion.div>
<AnimatePresence initial={false} onExitComplete={() => null}>
{showBlockAlert && block && (
<GreenAlert handleClose={closeBlock} text={friend + ' was successfully blocked'} />
)}
{showBlockAlert && !block && (
<RedAlert handleClose={closeBlock} text={friend + ' was not found'} />
)}
</AnimatePresence>
</TouchDiv>
{currentChat && isAdmin ? (
<TouchDiv>
<motion.div
onClick={() => (setting ? setSetting(false) : setSetting(true))}
>
<RiListSettingsLine/>
<AnimatePresence
initial={false}
onExitComplete={() => null}
>
{setting && <ModalSetting handleClose={closeSetting} convId={currentChat.id}/>}
</AnimatePresence>
</motion.div>
</TouchDiv>
):("")}
</div>
</div>
<div className="messages_box">
<div className="contact">

View File

@ -6,7 +6,7 @@
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 */
/* */
/* ************************************************************************** */

View File

@ -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);
setSelectedOptionArray(selectedOptions);
// 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,
}
let new_name;
try{
api.post("/conv", data);
handleClose();
} catch(err) {
console.log(err);
}
setSelectedOptionArray(selectedOptions);
}
// let new_name;
return (
<Backdrop>
<motion.div
@ -55,49 +107,27 @@ const Modal = ({handleClose, text}) => {
animate="visible"
exit="exit"
>
<p>New Convewrstion</p>
{/* <p>New Conversation</p> */}
{/* First selection */}
<select className="custom-select"
onChange={(e) => {
const selection = e.target.value;
selection === "group" ? setMulti(true) : setMulti(false)
}}>
<option value="1v1">1v1</option>
<option value="group">Group</option>
</select>
{/* Second selection */}
{selectTags.map((selectTag) => (
<div key={selectTag.id}>
<select
value={selectTag.selectedOption}
onChange={(a) => handleOptionChange(selectTag.id, a.target.value)}>
{Rank.map((item, index) => {
return (
<>
<option value={new_name}>{item.name}</option>
</>
)
})}
onChange={(a) => handleOptionChange(selectTag.id, a.target.value)}
>
<option value="">{
selectTag.selectedOption ? selectTag.selectedOption : "Select an option"
}</option>
{users.filter((item) => !selectTags.some((tag) => tag.selectedOption === item.name)).map((item, index) => (
<option key={index} value={item.username}>
{item.username}
</option>
))}
</select>
</div>
))
}
<div>
<h3>Selected Option:</h3>
<ul>
{selectedOptionArray.map((option, index) => (
<li key={index}>{option}</li>
))}
</ul>
</div>
<div>
{multi === true ? (
<GrAdd onClick={addNewSelectedTag}/>) : " "}
<GrAdd onClick={addNewSelectedTag}/>
</div>
<div className="div_submit">
<Link to='#' className="submit" onClick={ saveSelectedOptions}>Submit</Link>
@ -105,6 +135,55 @@ const Modal = ({handleClose, text}) => {
<Link to="#" className="submit" onClick={handleClose}>Cancel</Link>
</div>
{convs.length > 0 && (
<select
value={channel}
onChange={(event) => setChannel(event.target.value)}
>
<option value="">Select an option</option>
{convs.map((conv) => (
!(!conv.group || conv.private || (conv.banned && conv.banned.includes(channel)) || (conv.members && conv.members.includes(user.username))) && (
<option key={conv.id} value={conv.id}>
{conv.name}
</option>
)
))}
</select>
)}
<div className="div_submit">
<Link to='#' className="submit" onClick={ joinChannel }>Join</Link>
</div>
{/* {selectTags.map((selectTag) => (
<div key={selectTag.id}>
<select
value={selectTag.selectedOption}
onChange={(a) => handleOptionChange(selectTag.id, a.target.value)}
>
<option value="">{
selectTag.selectedOption ? selectTag.selectedOption : "Select an option"
}</option>
{convs.filter((item) => !selectTags.some((tag) => tag.selectedOption === item.name)).map((item, index) => (
<option key={index} value={item.name}>
{item.name}
</option>
))}
</select>
</div>
))} */}
{/* <div>
<GrAdd onClick={addNewSelectedTag}/>
</div> */}
</motion.div>
</Backdrop>
)

View File

@ -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 handleCheckpass = (e) => {
setPassword(e.target.checked);
}
const [multi, setMulti] = useState(false);
const [users, setUsers] = useState([]);
const [selectTags, setSelectTag] = useState([{ id: 1, selectedOption: ''}]);
const [selectedOptionArray, setSelectedOptionArray] = useState([]);
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 handleOptionChange = (selectId, selectedOption) => {
console.log("tag= ", selectTags)
console.log("option= ", selectedOption)
setSelectTag((prevTags) =>
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 saveSelectedOptions = () => {
const selectedOptions = selectTags.map((tag) => tag.selectedOption);
setSelectedOptionArray(selectedOptions);
const handleCheckPass = (e) => {
setPassword(e.target.checked);
console.log("password??", e.target.checked)
}
let new_name;
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();
};
return (
<Backdrop>
<motion.div
@ -60,95 +158,69 @@ const ModalSetting = ({handleClose, text}) => {
animate="visible"
exit="exit"
>
{/* <p>New Convewrstion</p> */}
{/* First selection */}
<div className="settingFirstPart">
<div>
<p className="checkbox">Private <input class="check"type="checkbox" value="private"/></p>
<p className="checkbox">PassW <input type="checkbox" value="password" checked={password} onChange={handleCheckpass}/> </p>
{password ? (<input type="text" className="in" placeholder="password"/>):("")}
<p className="checkbox">Private<input class="check"type="checkbox" value="private" onChange={handleCheckPriv}/></p>
<p className="checkbox">Password<input type="checkbox" value="password" checked={password} onChange={handleCheckPass}/> </p>
{password ? (
<input
onChange={(e) => setNewPassword(e.target.value)}
onKeyDown={handlePassword}
type="text"
className="in"
placeholder="Password"/>
):
("")}
</div>
<div className="forName">
<input type="text" className="in" placeholder="group name"/>
<input
onChange={(e) => setNewName(e.target.value)}
onKeyDown={handleName}
type="text"
className="in"
placeholder="New Name"
/>
</div>
</div>
{/* <select
onChange={(e) => {
const selection = e.target.value;
selection === "group" ? setMulti(true) : setMulti(false)
}}>
<option value="1v1">1v1</option>
<option value="group">Group</option>
</select> */}
{/* Second selection */}
<div className="settingSecondPart">
<Link to="#" className="submit" onClick={handleClose}>Send</Link>
{selectTags.map((selectTag) => (
<div key={selectTag.id}>
<select
value={selectTag.selectedOption}
onChange={(a) => handleOptionChange(selectTag.id, a.target.value)}>
{Rank.map((item, index) => {
return (
<>
<option >Select a name</option>
<option value={new_name}>{item.name}</option>
</>
)
})}
</select>
</div>
))
}
<div>
<Link to="#" className="submit">Ban</Link>
<Link to="#" className="submit">Mute</Link>
<Link to="#" className="submit">Admin</Link>
</div>
</div>
{/* {selectTags.map((selectTag) =>(
<div key={selectTag.id}>
<select
value={selectTag.selectedOption}
onChange={(a) => handleOptionChange(selectTag.id, a.target.value)}>
{Rank.map((item, index) => {
return (
<>
<option value={new_name}>{item.name}</option>
</>
)
})}
</select>
</div>
))
}
<div>
<h3>Selected Option:</h3>
<ul>
{selectedOptionArray.map((option, index) => (
<li key={index}>{option}</li>
onChange={(a) => handleOptionChange(selectTag.id, a.target.value)}
>
<option value="">
{selectTag.selectedOption ? selectTag.selectedOption : "Select an option"}
</option>
{users.map((item, index) => (
<option key={index} value={item.username}>
{item.username}
</option>
))}
</ul>
</select>
</div>
<div>
{multi === true ? (
<GrAdd onClick={addNewSelectedTag}/>) : " "}
</div>
<div className="div_submit">
<Link to='#' className="submit" onClick={ saveSelectedOptions}>Submit</Link>
))}
<Link to="#" className="submit" onClick={handleClose}>Cancel</Link>
</div> */}
<div>
<Link to="#" onClick={handleInvite} className="submit">Send</Link>
<Link to="#" onClick={handleBan} className="submit">Ban</Link>
<Link to="#" onClick={handleMute} className="submit">Mute</Link>
<Link to="#" onClick={handleAdmin} className="submit">Admin</Link>
</div>
</div>
</motion.div>
</Backdrop>

View File

@ -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 ) => {
<input className="text" type="text" value={nickname} onChange={handler} handleClose/>
<div onClick={handleClose}>
<div onClick={() => {UserProfile.UserName = nickname;}}>
<Link className="button">change</Link>
<Link className="button" to={""}>change</Link>
</div>
</div>
</motion.div>

View File

@ -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);

View File

@ -1,12 +1,12 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Friend.jsx :+: :+: :+: */
/* Friend.tsx :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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);

View File

@ -0,0 +1,111 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Friend.jsx :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 (
<UserChat>
{profilePicture ? (
<img className="pic-user" src={`data:image/jpeg;base64,${profilePicture}`} />
) : (
<img className="pic-user" src={DefaultPicture} alt="Default Profile Picture" />
)}
<div className="infoSideBar">
<span onClick={() => handleButtonClick(currentUser)}>{currentUser.nickname}</span>
<RxCircle icon={RxCircle} color={getStatus(currentUser)} />
<button onClick={() => handleSpectate(currentUser)} >Invite</button>
{getStatus(currentUser) !== 'blue' ? (
<></>
) : (
<button onClick={() => handleSpectate(currentUser)} >Spectate</button>
)}
</div>
</UserChat>
)
}

View File

@ -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,43 +50,41 @@ 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 (

View File

@ -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 (
<UserChat>
{profilePicture ? (
<img className="pic-user" src={`data:image/jpeg;base64,${profilePicture}`} />
) : (
<img className="pic-user" src={DefaultPicture} alt="Default Profile Picture" />
)}
<div className="infoSideBar">
<span onClick={() => handleButtonClick(currentUser)}>{currentUser.nickname}</span>
<RxCheckCircled onClick={() => Accept(request)} color={'green'}/>
<RxCircleBackslash onClick={() => Refuse(request)} color={'red'}/>
</div>
</UserChat>
)
}

View File

@ -44,7 +44,7 @@ function Social (){
try{
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);

View File

@ -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() {

View File

@ -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);
};

View File

@ -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
@ -41,6 +67,7 @@ export function drawCanvas() {
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()
@ -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);
}
});
requestAnimationFrame(draw);
console.log("retuuuuuuuuuuurn")
return (stopDrawCanvas);
}
export default DrawCanvas

View File

@ -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")}`

View File

@ -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;

View File

@ -157,3 +157,13 @@
font-size: 13px;
font-style: italic;
}
/* Messages.css */
/* import '../../styles/Messages.css' */
/* General styles */
/* Messages.css */
/* import '../../styles/Messages.css' */
/* General styles

2
containers/test Normal file
View File

@ -0,0 +1,2 @@
cc toi
cc 2

View File

@ -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
# 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