diff --git a/web/app.vue b/web/app.vue index 8f62b8b..5d634a8 100644 --- a/web/app.vue +++ b/web/app.vue @@ -1,3 +1,14 @@ + + diff --git a/web/assets/css/tailwind.css b/web/assets/css/tailwind.css index b5c61c9..af697a0 100644 --- a/web/assets/css/tailwind.css +++ b/web/assets/css/tailwind.css @@ -1,3 +1,17 @@ @tailwind base; @tailwind components; @tailwind utilities; + +@layer components { + .sidebar-item { + @apply font-medium text-lg w-full px-4 py-2 rounded hover:bg-white hover:bg-opacity-5 hover:cursor-pointer flex items-center + } + + .highlight { + @apply bg-primary bg-opacity-20 px-2 rounded + } +} + +.router-link-active { + background-color: rgba(0, 0, 0, 20%) +} diff --git a/web/assets/pictures/diamond_wall.png b/web/assets/pictures/diamond_wall.png new file mode 100644 index 0000000..df1a3ae Binary files /dev/null and b/web/assets/pictures/diamond_wall.png differ diff --git a/web/components/layout/Navbar.vue b/web/components/layout/Navbar.vue new file mode 100644 index 0000000..7d3f19a --- /dev/null +++ b/web/components/layout/Navbar.vue @@ -0,0 +1,19 @@ + + + diff --git a/web/components/layout/Sidebar.vue b/web/components/layout/Sidebar.vue new file mode 100644 index 0000000..8cf307b --- /dev/null +++ b/web/components/layout/Sidebar.vue @@ -0,0 +1,35 @@ + + + diff --git a/web/layouts/blank.vue b/web/layouts/blank.vue new file mode 100644 index 0000000..8f62b8b --- /dev/null +++ b/web/layouts/blank.vue @@ -0,0 +1,3 @@ + diff --git a/web/layouts/default.vue b/web/layouts/default.vue new file mode 100644 index 0000000..7bde4f5 --- /dev/null +++ b/web/layouts/default.vue @@ -0,0 +1,16 @@ + diff --git a/web/nuxt.config.ts b/web/nuxt.config.ts index 0f7fe91..cb9dc1e 100644 --- a/web/nuxt.config.ts +++ b/web/nuxt.config.ts @@ -14,5 +14,11 @@ export default defineNuxtConfig({ discordSecret: '', jwtSecret: '', dbUrl: '', + mineckerHost: '', + mineckerApiKey: '', + mincecraftContainer: 'mc-school', + public: { + redirectUrl: 'https://discord.com/api/oauth2/authorize?client_id=1052974736432443432&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fapi%2Fauth&response_type=code&scope=identify', + } } }) diff --git a/web/package-lock.json b/web/package-lock.json index 78c3e3d..fdc9351 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -12,15 +12,16 @@ "@xeovalyte/nuxt-xvui": "git+https://gitea.xeovalyte.dev/xeovalyte/nuxt-xvui.git", "jsonwebtoken": "^9.0.0", "mongodb": "^5.3.0", + "socket.io-client": "^4.6.1", "surrealdb.js": "^0.6.0" }, "devDependencies": { - "@nuxt/devtools": "^0.4.1", + "@nuxt/devtools": "^0.4.2", "@nuxtjs/eslint-module": "^4.0.2", "@nuxtjs/tailwindcss": "^6.6.6", "@types/node": "^18", - "eslint": "^8.38.0", - "nuxt": "^3.4.1", + "eslint": "^8.39.0", + "nuxt": "^3.4.2", "nuxt-icon": "^0.3.3" } }, @@ -1060,9 +1061,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.38.0.tgz", - "integrity": "sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==", + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.39.0.tgz", + "integrity": "sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng==", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } @@ -1487,14 +1488,14 @@ "dev": true }, "node_modules/@nuxt/devtools": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@nuxt/devtools/-/devtools-0.4.1.tgz", - "integrity": "sha512-c3FDYAtNRSEBlrbhLqPCALPgQQIP07sXUZ1XRuUIuFSTBxAKmvMhrwyrVxE9TSdUHvZNreSHt6vy3KD384eRJA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@nuxt/devtools/-/devtools-0.4.2.tgz", + "integrity": "sha512-+x+rC4Ur9bO7uP7fVkZkmkZUOoYKOxORQGXWb//QsfjtRQLmcTHGOyqZVj8GwB05WLCs//HOg433tJ6Yfxl7Lw==", "dev": true, "dependencies": { - "@nuxt/devtools-kit": "0.4.1", - "@nuxt/devtools-wizard": "0.4.1", - "@nuxt/kit": "^3.4.1", + "@nuxt/devtools-kit": "0.4.2", + "@nuxt/devtools-wizard": "0.4.2", + "@nuxt/kit": "^3.4.2", "birpc": "^0.2.11", "consola": "^3.1.0", "execa": "^7.1.1", @@ -1508,7 +1509,7 @@ "launch-editor": "^2.6.0", "local-pkg": "^0.4.3", "nypm": "^0.2.0", - "pacote": "^15.1.1", + "pacote": "^15.1.2", "pathe": "^1.1.0", "picocolors": "^1.0.0", "pkg-types": "^1.0.2", @@ -1517,7 +1518,7 @@ "sirv": "^2.0.2", "tinyws": "^0.1.0", "unimport": "^3.0.6", - "vite-plugin-inspect": "^0.7.22", + "vite-plugin-inspect": "^0.7.24", "vite-plugin-vue-inspector": "^3.4.0", "wait-on": "^7.0.1", "which": "^3.0.0", @@ -1527,36 +1528,36 @@ "devtools": "cli.mjs" }, "peerDependencies": { - "nuxt": "^3.3.1", + "nuxt": "^3.4.2", "vite": "*" } }, "node_modules/@nuxt/devtools-kit": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@nuxt/devtools-kit/-/devtools-kit-0.4.1.tgz", - "integrity": "sha512-iOtrvGKJNp+TkhyJl43jpkmAbVLbkc4lyUv4OWv8/s0RPEXTMRrTlw8llNcGp4DpT+y8ryOFInY/3z0f2l81Rg==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@nuxt/devtools-kit/-/devtools-kit-0.4.2.tgz", + "integrity": "sha512-I1AM4n6Z1KzjaFozFUsnw2M/B1o7pyNBmoOzf6TudkNO3DbmvwufRDXxmn2IghNqcaSibIu1IExfzHSVx5w6IQ==", "dev": true, "dependencies": { - "@nuxt/kit": "^3.4.1", - "@nuxt/schema": "^3.4.1", + "@nuxt/kit": "^3.4.2", + "@nuxt/schema": "^3.4.2", "execa": "^7.1.1" }, "peerDependencies": { - "nuxt": "^3.3.1", + "nuxt": "^3.4.2", "vite": "*" } }, "node_modules/@nuxt/devtools-wizard": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@nuxt/devtools-wizard/-/devtools-wizard-0.4.1.tgz", - "integrity": "sha512-y8HtwEWjmIzsM88iMLgub2EaYBJGUM7yedMNTId3FkpaPmZD0h01N65hLSlsWBo185WRrSXJWEkygvtjaUzv3w==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@nuxt/devtools-wizard/-/devtools-wizard-0.4.2.tgz", + "integrity": "sha512-8NShtoJtm3wYW2oXMWDiOY+2kwFkh8Q5ocwZTvdM0X2J9MBHZCHglsSC1OQHSKeFksd0hawjk+sao+r3Yz1hxA==", "dev": true, "dependencies": { "consola": "^3.1.0", "diff": "^5.1.0", "execa": "^7.1.1", "global-dirs": "^3.0.1", - "magicast": "^0.2.3", + "magicast": "^0.2.4", "pathe": "^1.1.0", "picocolors": "^1.0.0", "pkg-types": "^1.0.2", @@ -2124,6 +2125,11 @@ "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", "dev": true }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -4968,6 +4974,46 @@ "once": "^1.4.0" } }, + "node_modules/engine.io-client": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.4.0.tgz", + "integrity": "sha512-GyKPDyoEha+XZ7iEqam49vz6auPnNJ9ZBfy89f+rMMas8AuiMWOZ9PVzu8xb9ZC6rafUqiGHSCfu22ih66E+1g==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.11.0", + "xmlhttprequest-ssl": "~2.0.0" + } + }, + "node_modules/engine.io-client/node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/engine.io-parser": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz", + "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/enhanced-resolve": { "version": "5.13.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.13.0.tgz", @@ -5100,14 +5146,14 @@ } }, "node_modules/eslint": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.38.0.tgz", - "integrity": "sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg==", + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.39.0.tgz", + "integrity": "sha512-mwiok6cy7KTW7rBpo05k6+p4YVZByLNjAZ/ACB9DRCu4YDRwjXI01tWHp6KAUWelsBetTxKK/2sHB0vdS8Z2Og==", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", "@eslint/eslintrc": "^2.0.2", - "@eslint/js": "8.38.0", + "@eslint/js": "8.39.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -5117,7 +5163,7 @@ "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", + "eslint-scope": "^7.2.0", "eslint-visitor-keys": "^3.4.0", "espree": "^9.5.1", "esquery": "^1.4.2", @@ -11224,6 +11270,32 @@ "integrity": "sha512-V21+XeNni+tTyiST1MHsa84AQhT1aFZipzPpOFAVB8DkHzwJyjjAmt9bgwnuZiZWnIbMo2duE29wybxv/7HWUw==", "dev": true }, + "node_modules/socket.io-client": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.6.1.tgz", + "integrity": "sha512-5UswCV6hpaRsNg5kkEHVcbBIXEYoVbMQaHJBXJCyEQ+CiFPV1NIOY0XOFWG4XR4GZcB8Kn6AsRs/9cy9TbqVMQ==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.4.0", + "socket.io-parser": "~4.2.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz", + "integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/socks": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", @@ -13200,6 +13272,14 @@ "node": ">=12" } }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/xxhashjs": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz", @@ -13961,9 +14041,9 @@ } }, "@eslint/js": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.38.0.tgz", - "integrity": "sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==" + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.39.0.tgz", + "integrity": "sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng==" }, "@gar/promisify": { "version": "1.1.3", @@ -14292,14 +14372,14 @@ "dev": true }, "@nuxt/devtools": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@nuxt/devtools/-/devtools-0.4.1.tgz", - "integrity": "sha512-c3FDYAtNRSEBlrbhLqPCALPgQQIP07sXUZ1XRuUIuFSTBxAKmvMhrwyrVxE9TSdUHvZNreSHt6vy3KD384eRJA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@nuxt/devtools/-/devtools-0.4.2.tgz", + "integrity": "sha512-+x+rC4Ur9bO7uP7fVkZkmkZUOoYKOxORQGXWb//QsfjtRQLmcTHGOyqZVj8GwB05WLCs//HOg433tJ6Yfxl7Lw==", "dev": true, "requires": { - "@nuxt/devtools-kit": "0.4.1", - "@nuxt/devtools-wizard": "0.4.1", - "@nuxt/kit": "^3.4.1", + "@nuxt/devtools-kit": "0.4.2", + "@nuxt/devtools-wizard": "0.4.2", + "@nuxt/kit": "^3.4.2", "birpc": "^0.2.11", "consola": "^3.1.0", "execa": "^7.1.1", @@ -14313,7 +14393,7 @@ "launch-editor": "^2.6.0", "local-pkg": "^0.4.3", "nypm": "^0.2.0", - "pacote": "^15.1.1", + "pacote": "^15.1.2", "pathe": "^1.1.0", "picocolors": "^1.0.0", "pkg-types": "^1.0.2", @@ -14322,7 +14402,7 @@ "sirv": "^2.0.2", "tinyws": "^0.1.0", "unimport": "^3.0.6", - "vite-plugin-inspect": "^0.7.22", + "vite-plugin-inspect": "^0.7.24", "vite-plugin-vue-inspector": "^3.4.0", "wait-on": "^7.0.1", "which": "^3.0.0", @@ -14330,27 +14410,27 @@ } }, "@nuxt/devtools-kit": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@nuxt/devtools-kit/-/devtools-kit-0.4.1.tgz", - "integrity": "sha512-iOtrvGKJNp+TkhyJl43jpkmAbVLbkc4lyUv4OWv8/s0RPEXTMRrTlw8llNcGp4DpT+y8ryOFInY/3z0f2l81Rg==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@nuxt/devtools-kit/-/devtools-kit-0.4.2.tgz", + "integrity": "sha512-I1AM4n6Z1KzjaFozFUsnw2M/B1o7pyNBmoOzf6TudkNO3DbmvwufRDXxmn2IghNqcaSibIu1IExfzHSVx5w6IQ==", "dev": true, "requires": { - "@nuxt/kit": "^3.4.1", - "@nuxt/schema": "^3.4.1", + "@nuxt/kit": "^3.4.2", + "@nuxt/schema": "^3.4.2", "execa": "^7.1.1" } }, "@nuxt/devtools-wizard": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@nuxt/devtools-wizard/-/devtools-wizard-0.4.1.tgz", - "integrity": "sha512-y8HtwEWjmIzsM88iMLgub2EaYBJGUM7yedMNTId3FkpaPmZD0h01N65hLSlsWBo185WRrSXJWEkygvtjaUzv3w==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@nuxt/devtools-wizard/-/devtools-wizard-0.4.2.tgz", + "integrity": "sha512-8NShtoJtm3wYW2oXMWDiOY+2kwFkh8Q5ocwZTvdM0X2J9MBHZCHglsSC1OQHSKeFksd0hawjk+sao+r3Yz1hxA==", "dev": true, "requires": { "consola": "^3.1.0", "diff": "^5.1.0", "execa": "^7.1.1", "global-dirs": "^3.0.1", - "magicast": "^0.2.3", + "magicast": "^0.2.4", "pathe": "^1.1.0", "picocolors": "^1.0.0", "pkg-types": "^1.0.2", @@ -14777,6 +14857,11 @@ "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", "dev": true }, + "@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + }, "@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -16922,6 +17007,31 @@ "once": "^1.4.0" } }, + "engine.io-client": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.4.0.tgz", + "integrity": "sha512-GyKPDyoEha+XZ7iEqam49vz6auPnNJ9ZBfy89f+rMMas8AuiMWOZ9PVzu8xb9ZC6rafUqiGHSCfu22ih66E+1g==", + "requires": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.11.0", + "xmlhttprequest-ssl": "~2.0.0" + }, + "dependencies": { + "ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "requires": {} + } + } + }, + "engine.io-parser": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz", + "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==" + }, "enhanced-resolve": { "version": "5.13.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.13.0.tgz", @@ -17023,14 +17133,14 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" }, "eslint": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.38.0.tgz", - "integrity": "sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg==", + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.39.0.tgz", + "integrity": "sha512-mwiok6cy7KTW7rBpo05k6+p4YVZByLNjAZ/ACB9DRCu4YDRwjXI01tWHp6KAUWelsBetTxKK/2sHB0vdS8Z2Og==", "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", "@eslint/eslintrc": "^2.0.2", - "@eslint/js": "8.38.0", + "@eslint/js": "8.39.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -17040,7 +17150,7 @@ "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", + "eslint-scope": "^7.2.0", "eslint-visitor-keys": "^3.4.0", "espree": "^9.5.1", "esquery": "^1.4.2", @@ -21506,6 +21616,26 @@ "integrity": "sha512-V21+XeNni+tTyiST1MHsa84AQhT1aFZipzPpOFAVB8DkHzwJyjjAmt9bgwnuZiZWnIbMo2duE29wybxv/7HWUw==", "dev": true }, + "socket.io-client": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.6.1.tgz", + "integrity": "sha512-5UswCV6hpaRsNg5kkEHVcbBIXEYoVbMQaHJBXJCyEQ+CiFPV1NIOY0XOFWG4XR4GZcB8Kn6AsRs/9cy9TbqVMQ==", + "requires": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.4.0", + "socket.io-parser": "~4.2.1" + } + }, + "socket.io-parser": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz", + "integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==", + "requires": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + } + }, "socks": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", @@ -22892,6 +23022,11 @@ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==" }, + "xmlhttprequest-ssl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==" + }, "xxhashjs": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz", diff --git a/web/package.json b/web/package.json index 6db06ec..30b29f3 100644 --- a/web/package.json +++ b/web/package.json @@ -10,12 +10,12 @@ "lint": "eslint ." }, "devDependencies": { - "@nuxt/devtools": "^0.4.1", + "@nuxt/devtools": "^0.4.2", "@nuxtjs/eslint-module": "^4.0.2", "@nuxtjs/tailwindcss": "^6.6.6", "@types/node": "^18", - "eslint": "^8.38.0", - "nuxt": "^3.4.1", + "eslint": "^8.39.0", + "nuxt": "^3.4.2", "nuxt-icon": "^0.3.3" }, "dependencies": { @@ -24,6 +24,7 @@ "@xeovalyte/nuxt-xvui": "git+https://gitea.xeovalyte.dev/xeovalyte/nuxt-xvui.git", "jsonwebtoken": "^9.0.0", "mongodb": "^5.3.0", + "socket.io-client": "^4.6.1", "surrealdb.js": "^0.6.0" } } diff --git a/web/pages/index.vue b/web/pages/index.vue index d77452b..52939ac 100644 --- a/web/pages/index.vue +++ b/web/pages/index.vue @@ -1,6 +1,6 @@ diff --git a/web/pages/login.vue b/web/pages/login.vue index 63bf4a2..e975170 100644 --- a/web/pages/login.vue +++ b/web/pages/login.vue @@ -1,5 +1,20 @@ + + diff --git a/web/pages/whitelist.vue b/web/pages/whitelist.vue new file mode 100644 index 0000000..447b4f0 --- /dev/null +++ b/web/pages/whitelist.vue @@ -0,0 +1,38 @@ + + + diff --git a/web/server/api/auth/index.js b/web/server/api/auth/index.js index 870ab36..a472d9c 100644 --- a/web/server/api/auth/index.js +++ b/web/server/api/auth/index.js @@ -3,7 +3,7 @@ export default defineEventHandler(async (event) => { const config = useRuntimeConfig() - if (!code) sendRedirect(event, '/', 302) + if (!code) return sendRedirect(event, '/', 302) try { const tokenResponseData = await $fetch('https://discord.com/api/oauth2/token', { @@ -39,7 +39,7 @@ export default defineEventHandler(async (event) => { await coll.updateOne({ 'discord.id': userResult.id }, { $set: doc, $setOnInsert: { minecraft: { uuid: null, username: null }, team: null } }, { upsert: true }) - const token = createToken(tokenResponseData.access_token, tokenResponseData.refresh_token, tokenResponseData.expires_in) + const token = createToken(tokenResponseData.access_token, tokenResponseData.refresh_token, tokenResponseData.expires_in, userResult.id ) setCookie(event, 'jwt', token, { httpOnly: true, maxAge: tokenResponseData.expires_in * 1000 }) } catch (e) { diff --git a/web/server/api/minecraft/verifyuuid.js b/web/server/api/minecraft/verifyuuid.js new file mode 100644 index 0000000..e771a45 --- /dev/null +++ b/web/server/api/minecraft/verifyuuid.js @@ -0,0 +1,30 @@ +export default defineEventHandler(async (event) => { + const auth = getAuth(event) + + const { uuid } = await readBody(event) + + const coll = db.collection('whitelist') + + const doc = await coll.findOne({ uuid: uuid }) + + if (doc && !doc.verified) return { code: doc.code, verified: false } + if (doc && doc.verified) return { verified: true } + + await coll.createIndex({ code: 1 }, { unique: true }) + + const code = await insertDoc(coll, uuid) + + return { code: code.toString(), verified: false } +}); + +const insertDoc = async (coll, uuid) => { + try { + const code = Math.floor(100000 + Math.random() * 900000) + await coll.insertOne({ uuid: uuid, verified: false, code: code.toString() }) + + return code; + } catch (e) { + const code = await insertDoc(coll, uuid) + return code; + } +} diff --git a/web/server/api/minecraft/whitelist.js b/web/server/api/minecraft/whitelist.js new file mode 100644 index 0000000..98c9082 --- /dev/null +++ b/web/server/api/minecraft/whitelist.js @@ -0,0 +1,22 @@ +export default defineEventHandler(async (event) => { + const { code } = await readBody(event) + + if (!code) throw createError({ statusCode: 400, statusMessage: 'Code is required'}) + + const config = useRuntimeConfig() + const auth = await getAuth(event) + + const whitelistColl = db.collection('whitelist') + const whitelistDoc = await whitelistColl.findOne({ code: code.toString() }) + + if (!whitelistDoc) throw createError({ statusCode: 400, statusMessage: 'Code has not been found, join the server first' }) + if (whitelistDoc && whitelistDoc.verified) throw createError({ statusCode: 400, statusMessage: 'Already verified' }) + + await whitelistColl.updateOne({ code: code.toString() }, { $set: { verified: true } }) + + const usersColl = db.collection('users') + await usersColl.updateOne({ 'discord.id': auth.discord.id }, { $set: { 'minecraft.uuid': whitelistDoc.uuid } }) + + + return { uuid: whitelistDoc.uuid, verified: false } +}); diff --git a/web/server/utils/auth.js b/web/server/utils/auth.js index 0b6ead5..ce2bce6 100644 --- a/web/server/utils/auth.js +++ b/web/server/utils/auth.js @@ -2,11 +2,12 @@ import jwt from 'jsonwebtoken' const config = useRuntimeConfig() -export const createToken = (accessToken, refreshToken, maxAge) => { - return jwt.sign({ accessToken, refreshToken }, config.jwtSecret, { +export const createToken = (accessToken, refreshToken, maxAge, discordId) => { + return jwt.sign({ accessToken, refreshToken, discordId }, config.jwtSecret, { expiresIn: maxAge, }) } + export const getAuth = async (event) => { const token = getCookie(event, 'jwt') || null @@ -31,20 +32,9 @@ export const getAuth = async (event) => { }) } - let userResult; - try { - userResult = await $fetch('https://discord.com/api/users/@me', { - headers: { - authorization: `Bearer ${decodedToken.accessToken}` - } - }) - } catch (e) { - console.log(e) - } - try { const coll = db.collection("users") - const user = await coll.findOne({ 'discord.id': userResult.id }) + const user = await coll.findOne({ 'discord.id': decodedToken.discordId }) return user; } catch (err) { diff --git a/web/tailwind.config.js b/web/tailwind.config.js index 0a41687..46a8300 100644 --- a/web/tailwind.config.js +++ b/web/tailwind.config.js @@ -4,8 +4,14 @@ module.exports = { theme: { extend: { colors: { - primary: '#4bd6ef', + primary: '#3794B5', secondary: '#4bacef', + }, + gridTemplateColumns: { + 'desktoplayout': '14rem 1fr' + }, + gridTemplateRows: { + 'desktoplayout': '3rem 1fr' } }, },