diff --git a/index.js b/index.js index 1262a5c..e32ed36 100644 --- a/index.js +++ b/index.js @@ -15,12 +15,15 @@ import { MailAuth } from './utils/auth.js'; import { rateLimit } from 'express-rate-limit'; import { RedisStore as LimiterRedisStore } from 'rate-limit-redis'; import SessionRedisStore from 'connect-redis'; +import { I18n } from 'i18n'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const app = express(); +const flags = process.env.flags.split(","); + app.use(express.json()); app.use(express.urlencoded({ extended: true })); @@ -34,6 +37,11 @@ const redis = createClient(); redis.on('error', err => console.log('Redis Client Error', err)); await redis.connect(); +const i18n = new I18n({ + locales: ['en', 'pl'], + directory: path.join(__dirname, 'lang') +}); + const limiter = rateLimit({ windowMs: 40 * 1000, limit: 500, @@ -72,7 +80,7 @@ const sessionMiddleware = session({ saveUninitialized: true, rolling: true, cookie: { - secure: process.env.cookie_secure === "true" ? true : false, + secure: checkFlag("cookie_secure"), maxAge: 3 * 24 * 60 * 60 * 1000, }, }); @@ -137,13 +145,17 @@ app.post('/api/login', (req, res) => { if (login == 2) { res.redirect('/'); } else if (login == 0 && req.body.email != null && validateEmail(req.body.email)) { - auth.startVerification(req.body.email).then(result => { - if (result.status === 1) { + if (checkFlag('authless')) { + auth.loginAuthless(req.body.email).then(async result => { req.session.userId = result.uid; + req.session.loggedIn = 2; + res.redirect('/'); + }); - req.session.loggedIn = 1; - res.redirect('/auth'); - } else if (result.status === -1) { + return; + } + auth.startVerification(req.body.email, getIP(req, req.get('User-Agent'))).then(async result => { + if (result.status === 1 || result.status === -1) { req.session.userId = result.uid; req.session.loggedIn = 1; @@ -151,6 +163,14 @@ app.post('/api/login', (req, res) => { } else { res.sendStatus(500); } + }).catch((err) => { + res.render("error", { + helpers: { + error: "Wystąpił nieznany błąd logowania", + fallback: "/login" + } + }); + throw err; }); } else { res.render("error", { @@ -550,3 +570,15 @@ function validateEmail(email) { /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|.(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ ); }; + +function getIP(req) { + if (checkFlag("cloudflare_mode")) { + return req.headers['cf-connecting-ip']; + } else { + return req.headers['x-forwarded-for'] || req.socket.remoteAddress; + } +} + +function checkFlag(key) { + return flags.includes(key); +} \ No newline at end of file diff --git a/lang/en.json b/lang/en.json new file mode 100644 index 0000000..b60361c --- /dev/null +++ b/lang/en.json @@ -0,0 +1,65 @@ +{ + "errors": { + "Reonnecting...": "Reconnecting...", + "Reconnected": "Reconnected", + "Reconnection error occured": "Reconnection error occured", + "Reconection failed": "Reconnection failed", + "Disconnected": "Disconnected", + "Try to refresh the page if this error reoccurs": "Try to refresh the page if this error reoccurs", + "Connection error": "Connection error" + }, + "menu": { + "navbar": { + "Main menu": "Main menu", + "Profile": "Profile" + }, + "index": { + "Select game mode": "Select game mode", + "PvP": "PvP", + "Play against another player": "Play against another player", + "Vs. AI": "Vs. AI", + "Play against the computer": "Play against the computer" + }, + "PvP": { + "PvP": "PvP", + "Create": "Create", + "Create your own room": "Create your own room", + "Join": "Join", + "Join a room by a code": "Join a room by a code" + }, + "PvP/Create": { + "PvP / Create": "PvP / Create", + "Room code:": "Room code:", + "Waiting for an opponent": "Waiting for an opponent", + "Leave the room": "Leave the room" + }, + "PvP/Join": { + "PvP / Join": "PvP / Join", + "Room code": "Room code", + "Join": "Join" + }, + "PvP/Prepairing": { + "PvP / Loading": "PvP / Loading", + "Wait...": "Wait...", + "You will be redirected soon": "You will be redirected soon", + "Opponent:": "Opponent" + }, + "Profile": { + "Loading...": "Loading...", + "Player since: ": "Player since: ", + "Victory": "Victory", + "Defeat": "Defeat", + "Click to view match statistics": "Click to view match statistics", + "matches played this month": "matches played this month", + "total matches played": "total matches played", + "winrate": "winrate", + + "No matches played": "No matches played" + }, + + "General": { + "Unknown error occured": "Unknown error occured", + "Status:": "Status:" + } + } +} \ No newline at end of file diff --git a/lang/pl.json b/lang/pl.json new file mode 100644 index 0000000..e69de29 diff --git a/package-lock.json b/package-lock.json index a9a65ea..b6bcd59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,8 @@ "express-handlebars": "^7.1.2", "express-rate-limit": "^7.2.0", "express-session": "^1.18.0", + "geoip-lite": "^1.4.10", + "i18n": "^0.15.1", "mysql": "^2.18.1", "nodemailer": "^6.9.12", "rate-limit-redis": "^4.2.0", @@ -40,6 +42,45 @@ "node": ">=12" } }, + "node_modules/@messageformat/core": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@messageformat/core/-/core-3.3.0.tgz", + "integrity": "sha512-YcXd3remTDdeMxAlbvW6oV9d/01/DZ8DHUFwSttO3LMzIZj3iO0NRw+u1xlsNNORFI+u0EQzD52ZX3+Udi0T3g==", + "dependencies": { + "@messageformat/date-skeleton": "^1.0.0", + "@messageformat/number-skeleton": "^1.0.0", + "@messageformat/parser": "^5.1.0", + "@messageformat/runtime": "^3.0.1", + "make-plural": "^7.0.0", + "safe-identifier": "^0.4.1" + } + }, + "node_modules/@messageformat/date-skeleton": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@messageformat/date-skeleton/-/date-skeleton-1.0.1.tgz", + "integrity": "sha512-jPXy8fg+WMPIgmGjxSlnGJn68h/2InfT0TNSkVx0IGXgp4ynnvYkbZ51dGWmGySEK+pBiYUttbQdu5XEqX5CRg==" + }, + "node_modules/@messageformat/number-skeleton": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@messageformat/number-skeleton/-/number-skeleton-1.2.0.tgz", + "integrity": "sha512-xsgwcL7J7WhlHJ3RNbaVgssaIwcEyFkBqxHdcdaiJzwTZAWEOD8BuUFxnxV9k5S0qHN3v/KzUpq0IUpjH1seRg==" + }, + "node_modules/@messageformat/parser": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@messageformat/parser/-/parser-5.1.0.tgz", + "integrity": "sha512-jKlkls3Gewgw6qMjKZ9SFfHUpdzEVdovKFtW1qRhJ3WI4FW5R/NnGDqr8SDGz+krWDO3ki94boMmQvGke1HwUQ==", + "dependencies": { + "moo": "^0.5.1" + } + }, + "node_modules/@messageformat/runtime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@messageformat/runtime/-/runtime-3.0.1.tgz", + "integrity": "sha512-6RU5ol2lDtO8bD9Yxe6CZkl0DArdv0qkuoZC+ZwowU+cdRlVE1157wjCmlA5Rsf1Xc/brACnsZa5PZpEDfTFFg==", + "dependencies": { + "make-plural": "^7.0.0" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -167,6 +208,14 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -224,6 +273,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==" + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -232,6 +286,14 @@ "balanced-match": "^1.0.0" } }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "engines": { + "node": "*" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -258,6 +320,35 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/cluster-key-slot": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", @@ -282,6 +373,11 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, "node_modules/connect-redis": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/connect-redis/-/connect-redis-7.1.1.tgz", @@ -631,6 +727,25 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/fast-printf": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz", + "integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==", + "dependencies": { + "boolean": "^3.1.4" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dependencies": { + "pend": "~1.2.0" + } + }, "node_modules/finalhandler": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", @@ -692,6 +807,11 @@ "node": ">= 0.6" } }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -708,6 +828,23 @@ "node": ">= 4" } }, + "node_modules/geoip-lite": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/geoip-lite/-/geoip-lite-1.4.10.tgz", + "integrity": "sha512-4N69uhpS3KFd97m00wiFEefwa+L+HT5xZbzPhwu+sDawStg6UN/dPwWtUfkQuZkGIY1Cj7wDVp80IsqNtGMi2w==", + "dependencies": { + "async": "2.1 - 2.6.4", + "chalk": "4.1 - 4.1.2", + "iconv-lite": "0.4.13 - 0.6.3", + "ip-address": "5.8.9 - 5.9.4", + "lazy": "1.0.11", + "rimraf": "2.5.2 - 2.7.1", + "yauzl": "2.9.2 - 2.10.0" + }, + "engines": { + "node": ">=10.3.0" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -783,6 +920,14 @@ "uglify-js": "^3.1.4" } }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/has-property-descriptors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", @@ -842,6 +987,25 @@ "node": ">= 0.8" } }, + "node_modules/i18n": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/i18n/-/i18n-0.15.1.tgz", + "integrity": "sha512-yue187t8MqUPMHdKjiZGrX+L+xcUsDClGO0Cz4loaKUOK9WrGw5pgan4bv130utOwX7fHE9w2iUeHFalVQWkXA==", + "dependencies": { + "@messageformat/core": "^3.0.0", + "debug": "^4.3.3", + "fast-printf": "^1.6.9", + "make-plural": "^7.0.0", + "math-interval-parser": "^2.0.1", + "mustache": "^4.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/mashpie" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -853,11 +1017,33 @@ "node": ">=0.10.0" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/ip-address": { + "version": "5.9.4", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-5.9.4.tgz", + "integrity": "sha512-dHkI3/YNJq4b/qQaz+c8LuarD3pY24JqZWfjB8aZx1gtpc2MDILu9L9jpZe1sHpzo/yWFweQVn+U//FhazUxmw==", + "dependencies": { + "jsbn": "1.1.0", + "lodash": "^4.17.15", + "sprintf-js": "1.1.2" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -901,6 +1087,24 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + }, + "node_modules/lazy": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz", + "integrity": "sha512-Y+CjUfLmIpoUCCRl0ub4smrYtGGr5AOa2AKOaWelGHOGz33X/Y/KizefGqbkwfz44+cnq/+9habclf8vOmu2LA==", + "engines": { + "node": ">=0.2.0" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "node_modules/lru-cache": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", @@ -909,6 +1113,19 @@ "node": "14 || >=16.14" } }, + "node_modules/make-plural": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-7.3.0.tgz", + "integrity": "sha512-/K3BC0KIsO+WK2i94LkMPv3wslMrazrQhfi5We9fMbLlLjzoOSJWr7TAdupLlDWaJcWxwoNosBkhFDejiu5VDw==" + }, + "node_modules/math-interval-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/math-interval-parser/-/math-interval-parser-2.0.1.tgz", + "integrity": "sha512-VmlAmb0UJwlvMyx8iPhXUDnVW1F9IrGEd9CIOmv+XL8AErCUUuozoDMrgImvnYt2A+53qVX/tPW6YJurMKYsvA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -990,11 +1207,24 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/moo": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "bin": { + "mustache": "bin/mustache" + } + }, "node_modules/mysql": { "version": "2.18.1", "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", @@ -1070,6 +1300,14 @@ "node": ">= 0.8" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -1078,6 +1316,14 @@ "node": ">= 0.8" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -1106,6 +1352,11 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -1210,6 +1461,56 @@ "@redis/time-series": "1.0.5" } }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1229,6 +1530,11 @@ } ] }, + "node_modules/safe-identifier": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz", + "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==" + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -1402,6 +1708,11 @@ "node": ">=0.10.0" } }, + "node_modules/sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" + }, "node_modules/sqlstring": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", @@ -1519,6 +1830,17 @@ "node": ">=8" } }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -1716,6 +2038,11 @@ "node": ">=8" } }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, "node_modules/ws": { "version": "8.11.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", @@ -1740,6 +2067,15 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } } } } diff --git a/package.json b/package.json index 07b37f0..387fbf5 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,8 @@ "express-handlebars": "^7.1.2", "express-rate-limit": "^7.2.0", "express-session": "^1.18.0", + "geoip-lite": "^1.4.10", + "i18n": "^0.15.1", "mysql": "^2.18.1", "nodemailer": "^6.9.12", "rate-limit-redis": "^4.2.0", diff --git a/public/assets/js/socket.js b/public/assets/js/socket.js index a1533e4..b7b13dc 100644 --- a/public/assets/js/socket.js +++ b/public/assets/js/socket.js @@ -43,10 +43,10 @@ socket.emit("my profile", (profile) => { for (let i = 0; i < matchHistory.length; i++) { const match = matchHistory[i]; - let date = new Date(match.date).toLocaleDateString("pl-PL", options); + let date = new Date(match.date).toLocaleDateString(undefined, options); - const minutes = Math.floor(match.duration / 60).toLocaleString('pl-PL', { minimumIntegerDigits: 2, useGrouping: false }); - const seconds = (match.duration - minutes * 60).toLocaleString('pl-PL', { minimumIntegerDigits: 2, useGrouping: false }); + const seconds = (match.duration - minutes * 60).toLocaleString(undefined, { minimumIntegerDigits: 2, useGrouping: false }); + const minutes = Math.floor(match.duration / 60).toLocaleString(undefined, { minimumIntegerDigits: 2, useGrouping: false }); const duration = `${minutes}:${seconds}`; @@ -54,7 +54,7 @@ socket.emit("my profile", (profile) => { } if (matchHistoryDOM === "") { - matchHistoryDOM = "

Brak zagranych meczów

"; + matchHistoryDOM = `

${locale["No matches played"]}

`; } $(".matchList").html(matchHistoryDOM); @@ -84,7 +84,7 @@ $("#createGameButton").on("click", function () { break; default: - alert(`Wystąpił nieznany problem\nStatus: ${response.status}`); + alert(`${locale["Unknown error occured"]}\n${locale["Status:"]} ${response.status}`); lockUI(false); break; } @@ -122,7 +122,7 @@ form.addEventListener('submit', (e) => { // break; default: - alert(`Wystąpił nieznany problem\nStatus: ${response.status}`); + alert(`${locale["Unknown error occured"]}\n${locale["Status:"]} ${response.status}`); lockUI(false); switchView("mainMenuView"); break; diff --git a/utils/auth.js b/utils/auth.js index a72ada4..667cd5a 100644 --- a/utils/auth.js +++ b/utils/auth.js @@ -1,8 +1,8 @@ import nodemailer from 'nodemailer'; -import uuid4 from 'uuid4'; import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; +import geoip from 'geoip-lite'; import mysql from 'mysql'; import readline from "node:readline"; @@ -60,7 +60,35 @@ export class MailAuth { await this.redis.set(`loginTimer:${tId}`, -lastUpdate); } - startVerification(email) { + loginAuthless(email) { + return new Promise((resolve, reject) => { + const conn = mysql.createConnection(this.mysqlOptions); + conn.query(`SELECT user_id, nickname FROM accounts WHERE email = ${conn.escape(email)}`, async (error, response) => { + if (error) { reject(error); return; } + + if (response.length === 0 || response[0].nickname == null) { + if (response.length === 0) { + conn.query(`INSERT INTO accounts(email) VALUES (${conn.escape(email)});`, (error) => { if (error) reject(error) }); + } + + conn.query(`SELECT user_id FROM accounts WHERE email = ${conn.escape(email)}`, async (error, response) => { + if (error) reject(error); + const row = response[0]; + + resolve({ status: 1, uid: row.user_id }); + }); + + return; + } + + const row = response[0]; + + resolve({ status: 1, uid: row.user_id }); + }); + }); + } + + startVerification(email, ip, agent) { return new Promise((resolve, reject) => { const conn = mysql.createConnection(this.mysqlOptions); conn.query(`SELECT user_id, nickname FROM accounts WHERE email = ${conn.escape(email)}`, async (error, response) => { @@ -68,7 +96,7 @@ export class MailAuth { if (response.length !== 0) { let timer = await this.redis.get(`loginTimer:${response[0].user_id}`); if (timer && timer > 0) { - resolve({ status: -1, uid: response[0].user_id }); + resolve({ status: -1, uid: response[0].user_id, }); return; } } @@ -104,7 +132,7 @@ export class MailAuth { reject(e); } - resolve({ status: 1, uid: row.user_id }); + resolve({ status: 1, uid: row.user_id, code: authCode }); }); return; @@ -123,11 +151,15 @@ export class MailAuth { authCode = authCode.slice(0, 4) + " " + authCode.slice(4); + const lookup = geoip.lookup(ip); + + const lookupData = `User-Agent: ${agent}\nAdres IP: ${ip}\nKraj: ${lookup.country}\nRegion: ${lookup.region}\nMiasto: ${lookup.city}` + await this.mail.sendMail({ from: this.mailFrom, to: email, subject: `${authCode} to twój kod logowania do Statków`, - html: html.replace("{{ NICKNAME }}", row.nickname).replace("{{ CODE }}", authCode), + html: html.replace("{{ NICKNAME }}", row.nickname).replace("{{ CODE }}", authCode).replace("{{ LOOKUP }}", lookupData), }); resolve({ status: 1, uid: row.user_id }); diff --git a/utils/mail/auth-code-firsttime.html b/utils/mail/auth-code-firsttime.html index 1657d08..7f8afc7 100644 --- a/utils/mail/auth-code-firsttime.html +++ b/utils/mail/auth-code-firsttime.html @@ -19,6 +19,9 @@ {{ CODE }}

Powyższy kod wygasa po 10 minutach

+

Poniżej znajdują się informacje o logującym się urządzeniu*

+
{{ LOOKUP }}
+

* Dane lokalizacyjne mogą mijać się z prawdą. Traktuj je z dystansem

Copyright © 2024 MCJK |

Powyższy kod wygasa po 10 minutach

+

Poniżej znajdują się informacje o logującym się urządzeniu*

+
{{ LOOKUP }}
+

* Dane lokalizacyjne mogą mijać się z prawdą. Traktuj je z dystansem

Copyright © 2024 MCJK |

Kod pokoju:

- +

Oczekiwanie na gracza...

@@ -102,6 +102,11 @@ + \ No newline at end of file