Compare commits
10 Commits
ac17b5906e
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 19bb1942d8 | |||
| 11bf2e6807 | |||
| 65530963d7 | |||
| cccaf58ec3 | |||
| 020a2ae815 | |||
| f393496a1b | |||
| a805cb77fc | |||
| c282c6b597 | |||
| c420f643b7 | |||
| 8a4f98c5fd |
@@ -2,8 +2,13 @@ FROM node:22-bullseye
|
|||||||
|
|
||||||
WORKDIR /opt/mcserver
|
WORKDIR /opt/mcserver
|
||||||
|
|
||||||
COPY . .
|
COPY package.json package.json
|
||||||
|
COPY package-lock.json package-lock.json
|
||||||
|
|
||||||
RUN npm i
|
RUN npm i
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
ENTRYPOINT ["node", "./src/index.js"]
|
ENTRYPOINT ["node", "./src/index.js"]
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ canvas {
|
|||||||
margin-top: 0%;
|
margin-top: 0%;
|
||||||
border: solid 2px gray;
|
border: solid 2px gray;
|
||||||
box-shadow: 0px 20px 150px rgba(0, 0, 0, 1);
|
box-shadow: 0px 20px 150px rgba(0, 0, 0, 1);
|
||||||
|
height:100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-tabs {
|
.action-tabs {
|
||||||
@@ -134,3 +135,8 @@ canvas {
|
|||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.map-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 90%;
|
||||||
|
}
|
||||||
|
|||||||
@@ -44,9 +44,6 @@ $(document).ready(async () => {
|
|||||||
|
|
||||||
await onFetchMessageButtonClick();
|
await onFetchMessageButtonClick();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
socket.onmessage = message => {
|
socket.onmessage = message => {
|
||||||
try {
|
try {
|
||||||
message = JSON.parse(message.data)
|
message = JSON.parse(message.data)
|
||||||
|
|||||||
@@ -10,12 +10,16 @@ const uploadSkin = async (event) => {
|
|||||||
let formData = new FormData();
|
let formData = new FormData();
|
||||||
formData.append("file", skinFile);
|
formData.append("file", skinFile);
|
||||||
|
|
||||||
await fetch(`/api/uploadSkin`, {
|
const response = await fetch(`/api/uploadSkin`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: formData
|
body: formData
|
||||||
})
|
})
|
||||||
|
|
||||||
window.location = window.location.href+'?eraseCache=true';
|
if (response.status != 200) {
|
||||||
|
alert(await response.text())
|
||||||
|
} else {
|
||||||
|
window.location.reload(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const uploadCape = async (event) => {
|
const uploadCape = async (event) => {
|
||||||
@@ -30,15 +34,18 @@ const uploadCape = async (event) => {
|
|||||||
let formData = new FormData();
|
let formData = new FormData();
|
||||||
formData.append("file", capeFile);
|
formData.append("file", capeFile);
|
||||||
|
|
||||||
await fetch(`/api/uploadCape`, {
|
const response = await fetch(`/api/uploadCape`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: formData
|
body: formData
|
||||||
})
|
})
|
||||||
|
|
||||||
window.location = window.location.href+'?eraseCache=true';
|
if (response.status != 200) {
|
||||||
|
alert(await response.text())
|
||||||
|
} else {
|
||||||
|
window.location.reload(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
window.onload = async function() {
|
window.onload = async function() {
|
||||||
document.getElementById("skinForm").addEventListener("submit", uploadSkin)
|
document.getElementById("skinForm").addEventListener("submit", uploadSkin)
|
||||||
if (document.getElementById("cape")) {
|
if (document.getElementById("cape")) {
|
||||||
@@ -52,16 +59,19 @@ window.onload = async function() {
|
|||||||
document.getElementById("elytra").checked = false;
|
document.getElementById("elytra").checked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const username = await (await (fetch("/api/getUsername"))).text();
|
const username = await (await (fetch('/api/getUsername'))).text();
|
||||||
|
const skinsUrl = (await (await fetch('/api/skinsUrl')).text()).replace('%username%', username);
|
||||||
|
const capesUrl = (await (await fetch('/api/capesUrl')).text()).replace('%username%', username);
|
||||||
|
|
||||||
let skinViewer = new skinview3d.SkinViewer({
|
let skinViewer = new skinview3d.SkinViewer({
|
||||||
canvas: document.getElementById("skin_container"),
|
canvas: document.getElementById("skin_container"),
|
||||||
width: 300,
|
width: 300,
|
||||||
height: 400,
|
height: 400,
|
||||||
skin: `https://launcher.foxarmy.org/skins/${username}.png`,
|
skin: skinsUrl,
|
||||||
cape: `https://launcher.foxarmy.org/cloaks/${username}.png`
|
cape: capesUrl
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
skinViewer.nameTag = username;
|
skinViewer.nameTag = username;
|
||||||
skinViewer.loadPanorama("images/panorama.jpeg");
|
skinViewer.loadPanorama("images/panorama.jpeg");
|
||||||
skinViewer.fov = 120;
|
skinViewer.fov = 120;
|
||||||
@@ -69,7 +79,7 @@ window.onload = async function() {
|
|||||||
skinViewer.autoRotate = true;
|
skinViewer.autoRotate = true;
|
||||||
|
|
||||||
function set_cape_type(type) {
|
function set_cape_type(type) {
|
||||||
skinViewer.loadCape(`https://launcher.foxarmy.org/cloaks/${username}.png`, { backEquipment: type });
|
skinViewer.loadCape(capesUrl, { backEquipment: type });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
32
sample.env
32
sample.env
@@ -1,10 +1,30 @@
|
|||||||
SECRET=GENERATE_A_STRONG_SECRET_HERE
|
#Databse
|
||||||
DBUSER=mcserver
|
DBUSER=mcserver
|
||||||
DBHOST=localhost
|
DBHOST=database
|
||||||
DBNAME=mcserver
|
DBNAME=mcserver
|
||||||
DBPORT=5432
|
DBPORT=5433
|
||||||
DBPASS=GENERATE_A_STRONG_PASSWORD_HERE
|
DBPASS=GENERATE_A_STRONG_PASSWORD_HERE
|
||||||
PORT=3000
|
|
||||||
REQUIRE_TOKEN=false
|
#General
|
||||||
|
SECRET=GENERATE_A_STRONG_SECRET_HERE
|
||||||
|
APP_PORT=3000
|
||||||
|
|
||||||
|
#Token
|
||||||
|
REQUIRE_TOKEN=true
|
||||||
DELETE_TOKEN_ON_USE=true
|
DELETE_TOKEN_ON_USE=true
|
||||||
WS_CONNECTION_STRING=wss://auth.foxarmy.org
|
|
||||||
|
#Chat
|
||||||
|
ENABLE_CHAT=false
|
||||||
|
WS_CONNECTION_STRING=ws://localhost:3000
|
||||||
|
|
||||||
|
#Map
|
||||||
|
ENABLE_WORLDMAP=false
|
||||||
|
WORLDMAP_URL=http://localhost/map
|
||||||
|
|
||||||
|
#Skins
|
||||||
|
SKINS_TARGET_DIRECTORY=/opt/skins
|
||||||
|
SKINS_URL=https://launcher.foxarmy.org/skins/%username%.png
|
||||||
|
|
||||||
|
#Capes
|
||||||
|
CAPES_TARGET_DIRECTORY=/opt/cloaks
|
||||||
|
CAPES_URL=https://launcher.foxarmy.org/cloaks/%username%.png
|
||||||
33
src/config.js
Normal file
33
src/config.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import dotenv from 'dotenv';
|
||||||
|
|
||||||
|
dotenv.config({ path: ".env" });
|
||||||
|
|
||||||
|
const getBoolean = value => { return value === 'true'? true : false }
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
dbuser: process.env.DBUSER,
|
||||||
|
dbhost: process.env.DBHOST,
|
||||||
|
dbname: process.env.DBNAME,
|
||||||
|
dbport: Number.parseInt(process.env.DBPORT),
|
||||||
|
dbpass: process.env.DBPASS,
|
||||||
|
|
||||||
|
secret: process.env.SECRET,
|
||||||
|
app_port: Number.parseInt(process.env.APP_PORT),
|
||||||
|
|
||||||
|
require_token: getBoolean(process.env.REQUIRE_TOKEN),
|
||||||
|
delete_token_on_use: getBoolean(process.env.DELETE_TOKEN_ON_USE),
|
||||||
|
|
||||||
|
enable_chat: getBoolean(process.env.ENABLE_CHAT),
|
||||||
|
ws_connection_string: process.env.WS_CONNECTION_STRING,
|
||||||
|
|
||||||
|
enable_worldmap: getBoolean(process.env.ENABLE_WORLDMAP),
|
||||||
|
worldmap_url: process.env.WORLDMAP_URL,
|
||||||
|
|
||||||
|
skins_target_directory: process.env.SKINS_TARGET_DIRECTORY,
|
||||||
|
skins_url: process.env.SKINS_URL,
|
||||||
|
|
||||||
|
capes_target_directory: process.env.CAPES_TARGET_DIRECTORY,
|
||||||
|
capes_url: process.env.CAPES_URL
|
||||||
|
}
|
||||||
|
|
||||||
|
export default config;
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
import ApiService from "../services/api.js";
|
import ApiService from "../services/api.js";
|
||||||
import dotenv from 'dotenv';
|
import config from '../config.js';
|
||||||
|
|
||||||
dotenv.config({path: ".env"});
|
|
||||||
|
|
||||||
class ApiController {
|
class ApiController {
|
||||||
async getChatMessages(req, res) {
|
async getChatMessages(req, res) {
|
||||||
@@ -13,7 +11,15 @@ class ApiController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getWebsocketConnection(req, res) {
|
async getWebsocketConnection(req, res) {
|
||||||
return res.status(200).send(process.env.WS_CONNECTION_STRING)
|
return res.status(200).send(config.ws_connection_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getSkinsUrl(req, res) {
|
||||||
|
return res.status(200).send(config.skins_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getCapesUrl(req, res) {
|
||||||
|
return res.status(200).send(config.capes_url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
import bcrypt from 'bcrypt';
|
import bcrypt from 'bcrypt';
|
||||||
import jwt from 'jsonwebtoken';
|
import jwt from 'jsonwebtoken';
|
||||||
import dotenv from 'dotenv';
|
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { Jimp } from 'jimp';
|
import { Jimp } from 'jimp';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
|
||||||
import UserService from "../services/user.js";
|
import UserService from "../services/user.js";
|
||||||
import utils from '../utils.js';
|
import utils from '../utils.js';
|
||||||
|
import config from '../config.js';
|
||||||
|
|
||||||
dotenv.config({path: ".env"});
|
|
||||||
class UserController {
|
class UserController {
|
||||||
async register(req, res) {
|
async register(req, res) {
|
||||||
const { username, password } = req.body;
|
const { username, password } = req.body;
|
||||||
@@ -27,24 +26,24 @@ class UserController {
|
|||||||
|
|
||||||
await UserService.register(username, hashedPassword);
|
await UserService.register(username, hashedPassword);
|
||||||
|
|
||||||
if (process.env.REQUIRE_TOKEN == "true" && process.env.DELETE_TOKEN_ON_USE == "true") {
|
if (config.require_token && config.delete_token_on_use) {
|
||||||
utils.removeFromFile('./inviteTokens.txt', req.body.inviteToken);
|
utils.removeFromFile('./inviteTokens.txt', req.body.inviteToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
const token = jwt.sign({ username }, process.env.SECRET, {expiresIn: "1y"});
|
const token = jwt.sign({ username }, config.secret, { expiresIn: "1y" });
|
||||||
res.cookie("jwt", token);
|
res.cookie("jwt", token);
|
||||||
return res.status(200).send("Ok");
|
return res.status(200).send("Ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
async login(req, res) {
|
async login(req, res) {
|
||||||
const {username, password} = req.body;
|
const { username, password } = req.body;
|
||||||
|
|
||||||
const storedPassword = await UserService.getPassword(username);
|
const storedPassword = await UserService.getPassword(username);
|
||||||
|
|
||||||
if (!bcrypt.compareSync(password, storedPassword)) {
|
if (!bcrypt.compareSync(password, storedPassword)) {
|
||||||
return res.status(403).send("Password is not correct");
|
return res.status(403).send("Password is not correct");
|
||||||
}
|
}
|
||||||
const token = jwt.sign({ username }, process.env.SECRET, {expiresIn: "1y"});
|
const token = jwt.sign({ username }, config.secret, { expiresIn: "1y" });
|
||||||
res.cookie("jwt", token);
|
res.cookie("jwt", token);
|
||||||
return res.status(200).send("Ok");
|
return res.status(200).send("Ok");
|
||||||
}
|
}
|
||||||
@@ -77,21 +76,28 @@ class UserController {
|
|||||||
const token = req.cookies["jwt"];
|
const token = req.cookies["jwt"];
|
||||||
const decoded = jwt.decode(token);
|
const decoded = jwt.decode(token);
|
||||||
const tempPath = req.file.path;
|
const tempPath = req.file.path;
|
||||||
const targetPath = `/opt/skins/${decoded.username}.png`;
|
const targetPath = config.skins_target_directory + `/${decoded.username}.png`;
|
||||||
|
|
||||||
if (path.extname(req.file.originalname).toLowerCase() !== ".png") {
|
if (path.extname(req.file.originalname).toLowerCase() !== ".png") {
|
||||||
return res.status(400).send("Only .png files are allowed!");
|
return res.status(400).send("Only .png files are allowed!");
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
const image = await Jimp.read(tempPath);
|
||||||
const image = await Jimp.read(tempPath);
|
} catch (err) {
|
||||||
if (image.bitmap.width != 64 || image.bitmap.height != 64) {
|
console.log(`Error during cape installation, ${err}`)
|
||||||
|
return res.status(500).send("Internal server error. Please, report to the developer.")
|
||||||
|
}
|
||||||
|
const allowedWidths = [32, 64, 128];
|
||||||
|
const allowedHeights = [32, 64];
|
||||||
|
if (!allowedWidths.includes(image.bitmap.width) || !allowedHeights.includes(image.bitmap.height)) {
|
||||||
return res.status(400).send('This does not look like a minecraft skin.');
|
return res.status(400).send('This does not look like a minecraft skin.');
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
fs.renameSync(tempPath, targetPath, err => {
|
await fs.promises.cp(tempPath, targetPath);
|
||||||
if (err) return res.status(500).send("Ooops! Something went wrong! Please, report to the developer.");
|
await fs.promises.unlink(tempPath);
|
||||||
});
|
} catch (err) {
|
||||||
|
return res.status(500).send("Ooops! Something went wrong! Please, report to the developer.");
|
||||||
|
}
|
||||||
return res.status(200).send("Skin uploaded!");
|
return res.status(200).send("Skin uploaded!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,21 +105,28 @@ class UserController {
|
|||||||
const token = req.cookies["jwt"];
|
const token = req.cookies["jwt"];
|
||||||
const decoded = jwt.decode(token);
|
const decoded = jwt.decode(token);
|
||||||
const tempPath = req.file.path;
|
const tempPath = req.file.path;
|
||||||
const targetPath = `/opt/cloaks/${decoded.username}.png`;
|
const targetPath = config.capes_target_directory + `/${decoded.username}.png`;
|
||||||
|
|
||||||
if (path.extname(req.file.originalname).toLowerCase() !== ".png") {
|
if (path.extname(req.file.originalname).toLowerCase() !== ".png") {
|
||||||
return res.status(400).send("Only .png files are allowed!");
|
return res.status(400).send("Only .png files are allowed!");
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
const image = await Jimp.read(tempPath);
|
||||||
const image = await Jimp.read(tempPath);
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.log(`Error during cape installation, ${err}`)
|
||||||
|
return res.status(500).send("Internal server error. Please, report to the developer.")
|
||||||
|
}
|
||||||
if ((image.bitmap.width != 64 || image.bitmap.height != 32) && (image.bitmap.width != 128 || image.bitmap.height != 64)) {
|
if ((image.bitmap.width != 64 || image.bitmap.height != 32) && (image.bitmap.width != 128 || image.bitmap.height != 64)) {
|
||||||
return res.status(400).send('This does not look like a minecraft cape.');
|
return res.status(400).send('This does not look like a minecraft cape.');
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.renameSync(tempPath, targetPath, err => {
|
try {
|
||||||
if (err) return res.status(500).send("Ooops! Something went wrong! Please, report to the developer.");
|
await fs.promises.cp(tempPath, targetPath);
|
||||||
});
|
await fs.promises.unlink(tempPath);
|
||||||
|
} catch (err) {
|
||||||
|
return res.status(500).send("Ooops! Something went wrong! Please, report to the developer.");
|
||||||
|
}
|
||||||
|
|
||||||
return res.status(200).send("Cape uploaded!");
|
return res.status(200).send("Cape uploaded!");
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/db.js
13
src/db.js
@@ -1,19 +1,18 @@
|
|||||||
import pg from 'pg';
|
import pg from 'pg';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import dotenv from 'dotenv';
|
|
||||||
|
|
||||||
dotenv.config({path: ".env"});
|
import config from './config.js';
|
||||||
|
|
||||||
const { Pool } = pg;
|
const { Pool } = pg;
|
||||||
|
|
||||||
console.log("Connecting to PostgreSQL database");
|
console.log("Connecting to PostgreSQL database");
|
||||||
|
|
||||||
const pool = new Pool({
|
const pool = new Pool({
|
||||||
user: process.env.DBUSER,
|
user: config.dbuser,
|
||||||
host: process.env.DBHOST,
|
host: config.dbhost,
|
||||||
database: process.env.DBNAME,
|
database: config.dbnape,
|
||||||
password: process.env.DBPASS,
|
password: config.dbpass,
|
||||||
port: process.env.DBPORT
|
port: config.dbport
|
||||||
});
|
});
|
||||||
|
|
||||||
pool.query(fs.readFileSync('./db_schema.psql').toString());
|
pool.query(fs.readFileSync('./db_schema.psql').toString());
|
||||||
|
|||||||
13
src/index.js
13
src/index.js
@@ -1,5 +1,4 @@
|
|||||||
import express from 'express';
|
import express from 'express';
|
||||||
import dotenv from 'dotenv';
|
|
||||||
import session from 'express-session';
|
import session from 'express-session';
|
||||||
import cookieParser from 'cookie-parser';
|
import cookieParser from 'cookie-parser';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
@@ -7,13 +6,12 @@ import path from 'path';
|
|||||||
import ApiRouter from './routers/api.js';
|
import ApiRouter from './routers/api.js';
|
||||||
import UserRouter from './routers/user.js';
|
import UserRouter from './routers/user.js';
|
||||||
import startChat from './messages.js';
|
import startChat from './messages.js';
|
||||||
|
import config from './config.js';
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
dotenv.config({ path: ".env" });
|
|
||||||
|
|
||||||
app.use(session({
|
app.use(session({
|
||||||
secret: process.env.SECRET,
|
secret: config.secret,
|
||||||
resave: true,
|
resave: true,
|
||||||
saveUninitialized: false,
|
saveUninitialized: false,
|
||||||
cookie: { maxAge: 1000 * 60 * 60 * 24 }
|
cookie: { maxAge: 1000 * 60 * 60 * 24 }
|
||||||
@@ -28,9 +26,12 @@ app.set('view engine', 'pug');
|
|||||||
app.use('/api', ApiRouter);
|
app.use('/api', ApiRouter);
|
||||||
app.use('/', UserRouter);
|
app.use('/', UserRouter);
|
||||||
|
|
||||||
const server = app.listen(process.env.PORT, () => {
|
const server = app.listen(config.app_port, () => {
|
||||||
console.log("App has been started!");
|
console.log("App has been started!");
|
||||||
startChat();
|
|
||||||
|
if(config.enable_chat) {
|
||||||
|
startChat();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default server;
|
export default server;
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import dotenv from 'dotenv';
|
|
||||||
import jwt from 'jsonwebtoken';
|
import jwt from 'jsonwebtoken';
|
||||||
|
|
||||||
import UserService from '../services/user.js';
|
import UserService from '../services/user.js';
|
||||||
|
import config from '../config.js';
|
||||||
|
|
||||||
dotenv.config({path: ".env"});
|
|
||||||
|
|
||||||
const authenticate = async (req, res, next) => {
|
const authenticate = async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
const token = req.cookies["jwt"];
|
const token = req.cookies["jwt"];
|
||||||
if (!token || !jwt.verify(token, process.env.SECRET)) {
|
if (!token || !jwt.verify(token, config.secret)) {
|
||||||
req.session.destroy();
|
req.session.destroy();
|
||||||
res.clearCookie("jwt");
|
res.clearCookie("jwt");
|
||||||
return res.redirect("/login");
|
return res.redirect("/login");
|
||||||
@@ -17,11 +16,14 @@ const authenticate = async (req, res, next) => {
|
|||||||
next();
|
next();
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
|
req.session.destroy();
|
||||||
|
res.clearCookie("jwt");
|
||||||
|
return res.redirect("/login");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const validateInviteToken = async (req, res, next) => {
|
const validateInviteToken = async (req, res, next) => {
|
||||||
if (process.env.REQUIRE_TOKEN != "true") return next();
|
if (!config.require_token) return next();
|
||||||
|
|
||||||
const { inviteToken } = req.body;
|
const { inviteToken } = req.body;
|
||||||
if (!inviteToken || inviteToken == "") return res.status(400).send("Token is not valid");
|
if (!inviteToken || inviteToken == "") return res.status(400).send("Token is not valid");
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import dotenv from 'dotenv';
|
|
||||||
import jwt from 'jsonwebtoken';
|
import jwt from 'jsonwebtoken';
|
||||||
|
|
||||||
import UserService from '../services/user.js';
|
import UserService from '../services/user.js';
|
||||||
|
import config from '../config.js';
|
||||||
dotenv.config({path: ".env"});
|
|
||||||
|
|
||||||
const userDoesNotExist = async (req, res, next) => {
|
const userDoesNotExist = async (req, res, next) => {
|
||||||
|
|
||||||
@@ -20,7 +18,7 @@ const userExist = async (req, res, next) => {
|
|||||||
if (req.body.username) {
|
if (req.body.username) {
|
||||||
username = req.body.username;
|
username = req.body.username;
|
||||||
} else if (req.cookies["jwt"]) {
|
} else if (req.cookies["jwt"]) {
|
||||||
if (!req.cookies["jwt"] || !jwt.verify(req.cookies["jwt"], process.env.SECRET)) {
|
if (!req.cookies["jwt"] || !jwt.verify(req.cookies["jwt"], config.secret)) {
|
||||||
return res.status(403).send("Unauthorized");
|
return res.status(403).send("Unauthorized");
|
||||||
}
|
}
|
||||||
username = jwt.decode(req.cookies["jwt"]).username;
|
username = jwt.decode(req.cookies["jwt"]).username;
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import dotenv from 'dotenv';
|
import config from '../config.js';
|
||||||
|
|
||||||
dotenv.config({path: ".env"});
|
|
||||||
|
|
||||||
const requireUsername = async (req, res, next) => {
|
const requireUsername = async (req, res, next) => {
|
||||||
const { username } = req.body;
|
const { username } = req.body;
|
||||||
@@ -19,7 +17,7 @@ const requirePassword = async (req, res, next) => {
|
|||||||
const requireInviteToken = async (req, res, next) => {
|
const requireInviteToken = async (req, res, next) => {
|
||||||
const { inviteToken } = req.body;
|
const { inviteToken } = req.body;
|
||||||
|
|
||||||
if (!inviteToken && process.env.REQUIRE_TOKEN == "true") return res.status(400).send("Invite token is required");
|
if (!inviteToken && config.require_token) return res.status(400).send("Invite token is required");
|
||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -14,10 +14,15 @@ ApiRouter.post('/register', requiredParameters.requireUsername, requiredParamete
|
|||||||
ApiRouter.post('/login', requiredParameters.requireUsername, requiredParameters.requirePassword, existance.userExist, UserController.login);
|
ApiRouter.post('/login', requiredParameters.requireUsername, requiredParameters.requirePassword, existance.userExist, UserController.login);
|
||||||
ApiRouter.get('/logout', auth.authenticate, UserController.logout);
|
ApiRouter.get('/logout', auth.authenticate, UserController.logout);
|
||||||
ApiRouter.post('/changepassword', auth.authenticate, existance.userExist, UserController.changePassword);
|
ApiRouter.post('/changepassword', auth.authenticate, existance.userExist, UserController.changePassword);
|
||||||
|
|
||||||
ApiRouter.post('/uploadSkin', existance.userExist, auth.authenticate, utils.upload.single('file'), requiredParameters.requireFile, UserController.uploadSkin);
|
ApiRouter.post('/uploadSkin', existance.userExist, auth.authenticate, utils.upload.single('file'), requiredParameters.requireFile, UserController.uploadSkin);
|
||||||
ApiRouter.post('/uploadCape', existance.userExist, auth.authenticate, auth.canHaveCloak, utils.upload.single('file'), requiredParameters.requireFile, UserController.uploadCape);
|
ApiRouter.post('/uploadCape', existance.userExist, auth.authenticate, auth.canHaveCloak, utils.upload.single('file'), requiredParameters.requireFile, UserController.uploadCape);
|
||||||
|
|
||||||
ApiRouter.get('/getUsername', existance.userExist, auth.authenticate, UserController.getUsername);
|
ApiRouter.get('/getUsername', existance.userExist, auth.authenticate, UserController.getUsername);
|
||||||
ApiRouter.get('/getChatMessages/:offset/:limit', auth.authenticate, ApiController.getChatMessages);
|
ApiRouter.get('/getChatMessages/:offset/:limit', auth.authenticate, ApiController.getChatMessages);
|
||||||
ApiRouter.get('/webSocketConnection', auth.authenticate, ApiController.getWebsocketConnection)
|
ApiRouter.get('/webSocketConnection', auth.authenticate, ApiController.getWebsocketConnection);
|
||||||
|
|
||||||
|
ApiRouter.get('/skinsUrl', auth.authenticate, ApiController.getSkinsUrl);
|
||||||
|
ApiRouter.get('/capesUrl', auth.authenticate, ApiController.getCapesUrl);
|
||||||
|
|
||||||
export default ApiRouter;
|
export default ApiRouter;
|
||||||
@@ -1,25 +1,23 @@
|
|||||||
import { Router } from 'express';
|
import { Router } from 'express';
|
||||||
import jwt from 'jsonwebtoken';
|
import jwt from 'jsonwebtoken';
|
||||||
import dotenv from 'dotenv';
|
|
||||||
|
|
||||||
import auth from '../middlewares/auth.js';
|
import auth from '../middlewares/auth.js';
|
||||||
import UserService from '../services/user.js';
|
import UserService from '../services/user.js';
|
||||||
|
import config from '../config.js';
|
||||||
dotenv.config({path: ".env"});
|
|
||||||
|
|
||||||
const UserRouter = new Router();
|
const UserRouter = new Router();
|
||||||
|
|
||||||
UserRouter.get('/register', async (req, res) => {
|
UserRouter.get('/register', async (req, res) => {
|
||||||
if (req.cookies["jwt"] && jwt.verify(req.cookies["jwt"], process.env.SECRET))
|
if (req.cookies["jwt"] && jwt.verify(req.cookies["jwt"], config.secret))
|
||||||
return res.redirect("/index");
|
return res.redirect("/index");
|
||||||
|
|
||||||
return res.render("register.pug", {
|
return res.render("register.pug", {
|
||||||
require_token: process.env.REQUIRE_TOKEN == "true"? true : false
|
require_token: config.require_token? true : false
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
UserRouter.get(['/', '/login'], async (req, res) => {
|
UserRouter.get(['/', '/login'], async (req, res) => {
|
||||||
if(req.cookies["jwt"] && jwt.verify(req.cookies["jwt"], process.env.SECRET)) {
|
if(req.cookies["jwt"] && jwt.verify(req.cookies["jwt"], config.secret)) {
|
||||||
return res.redirect("/index");
|
return res.redirect("/index");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,7 +29,9 @@ UserRouter.get(['/index', '/skin'], auth.authenticate, async (req, res) => {
|
|||||||
|
|
||||||
return res.render('skin.pug', {
|
return res.render('skin.pug', {
|
||||||
username: username,
|
username: username,
|
||||||
can_have_cloak: await UserService.canHaveCloak(username)
|
can_have_cloak: await UserService.canHaveCloak(username),
|
||||||
|
enable_chat: config.enable_chat,
|
||||||
|
enable_worldmap: config.enable_worldmap
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -39,7 +39,9 @@ UserRouter.get('/changepassword', auth.authenticate, async (req, res) => {
|
|||||||
const username = jwt.decode(req.cookies["jwt"]).username;
|
const username = jwt.decode(req.cookies["jwt"]).username;
|
||||||
|
|
||||||
return res.render('changepassword.pug', {
|
return res.render('changepassword.pug', {
|
||||||
can_have_cloak: await UserService.canHaveCloak(username)
|
can_have_cloak: await UserService.canHaveCloak(username),
|
||||||
|
enable_chat: config.enable_chat,
|
||||||
|
enable_worldmap: config.enable_worldmap
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -47,7 +49,9 @@ UserRouter.get('/chat', auth.authenticate, async (req, res) => {
|
|||||||
const username = jwt.decode(req.cookies["jwt"]).username;
|
const username = jwt.decode(req.cookies["jwt"]).username;
|
||||||
|
|
||||||
return res.render('chat.pug', {
|
return res.render('chat.pug', {
|
||||||
can_have_cloak: await UserService.canHaveCloak(username)
|
can_have_cloak: await UserService.canHaveCloak(username),
|
||||||
|
enable_chat: config.enable_chat,
|
||||||
|
enable_worldmap: config.enable_worldmap
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -55,7 +59,10 @@ UserRouter.get('/worldmap', auth.authenticate, async (req, res) => {
|
|||||||
const username = jwt.decode(req.cookies["jwt"]).username;
|
const username = jwt.decode(req.cookies["jwt"]).username;
|
||||||
|
|
||||||
return res.render('worldmap.pug', {
|
return res.render('worldmap.pug', {
|
||||||
can_have_cloak: await UserService.canHaveCloak(username)
|
can_have_cloak: await UserService.canHaveCloak(username),
|
||||||
|
enable_worldmap: config.enable_worldmap,
|
||||||
|
enable_chat: config.enable_chat,
|
||||||
|
worldmap_url: config.worldmap_url
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ div(class="action-tabs")
|
|||||||
else
|
else
|
||||||
button(class="actionTabButton" id="skinsTabButton" onclick="goToPage('/index')") Скин
|
button(class="actionTabButton" id="skinsTabButton" onclick="goToPage('/index')") Скин
|
||||||
button(class="actionTabButton" id="passwordChangeTabButton" onclick="goToPage('/changepassword')") Сменить пароль
|
button(class="actionTabButton" id="passwordChangeTabButton" onclick="goToPage('/changepassword')") Сменить пароль
|
||||||
button(class="actionTabButton" id="chatTabButton" onclick="goToPage('/chat')") Чат
|
if (enable_chat)
|
||||||
button(class="actionTabButton" id="chatTabButton" onclick="goToPage('/worldmap')") Карта мира
|
button(class="actionTabButton" id="chatTabButton" onclick="goToPage('/chat')") Чат
|
||||||
|
if (enable_worldmap)
|
||||||
|
button(class="actionTabButton" id="chatTabButton" onclick="goToPage('/worldmap')") Карта мира
|
||||||
button(class="actionTabButton logoutTabButton" id="logoutTabButton" onclick="window.location.href='/api/logout'") Выйти
|
button(class="actionTabButton logoutTabButton" id="logoutTabButton" onclick="window.location.href='/api/logout'") Выйти
|
||||||
@@ -10,4 +10,4 @@ html
|
|||||||
div(class="content-container")
|
div(class="content-container")
|
||||||
div(class="map-container")
|
div(class="map-container")
|
||||||
h1 Карта
|
h1 Карта
|
||||||
p Пока что тут пусто, но скоро будет кое-что интересное!
|
iframe(src=worldmap_url class="map-container")
|
||||||
|
|||||||
Reference in New Issue
Block a user