switch from req.session.jwt to cookies
This commit is contained in:
parent
c0ee036530
commit
3a742b1f34
|
@ -0,0 +1,64 @@
|
|||
<mxfile host="app.diagrams.net" agent="Mozilla/5.0 (X11; Linux x86_64; rv:134.0) Gecko/20100101 Firefox/134.0" version="26.0.10">
|
||||
<diagram name="Page-1" id="nvzCRnp9_quasQS-yvnN">
|
||||
<mxGraphModel dx="1434" dy="751" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="69ARyxQlwhHyFWX5DNmJ-3" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="70" y="60" width="170" height="90" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="69ARyxQlwhHyFWX5DNmJ-5" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="650" y="60" width="170" height="90" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="69ARyxQlwhHyFWX5DNmJ-6" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="340" y="330" width="170" height="90" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="69ARyxQlwhHyFWX5DNmJ-7" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="340" y="600" width="170" height="90" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="69ARyxQlwhHyFWX5DNmJ-9" value="<font style="font-size: 22px;">Frontend</font>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="110" y="90" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="69ARyxQlwhHyFWX5DNmJ-10" value="<font style="font-size: 22px;">Backend</font>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="700" y="90" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="69ARyxQlwhHyFWX5DNmJ-11" value="<div><font style="font-size: 22px;">Kafka</font></div>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="390" y="350" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="69ARyxQlwhHyFWX5DNmJ-13" value="<font style="font-size: 22px;">MC Server<br></font>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="390" y="630" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="69ARyxQlwhHyFWX5DNmJ-14" value="" style="shape=flexArrow;endArrow=classic;startArrow=classic;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="69ARyxQlwhHyFWX5DNmJ-3" target="69ARyxQlwhHyFWX5DNmJ-5">
|
||||
<mxGeometry width="100" height="100" relative="1" as="geometry">
|
||||
<mxPoint x="370" y="440" as="sourcePoint" />
|
||||
<mxPoint x="470" y="340" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="69ARyxQlwhHyFWX5DNmJ-16" value="websocket" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="390" y="60" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="69ARyxQlwhHyFWX5DNmJ-17" value="" style="shape=flexArrow;endArrow=classic;startArrow=classic;html=1;rounded=0;entryX=0.465;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;exitX=1;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="69ARyxQlwhHyFWX5DNmJ-6" target="69ARyxQlwhHyFWX5DNmJ-5">
|
||||
<mxGeometry width="100" height="100" relative="1" as="geometry">
|
||||
<mxPoint x="630" y="310" as="sourcePoint" />
|
||||
<mxPoint x="470" y="340" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="69ARyxQlwhHyFWX5DNmJ-18" value="" style="shape=flexArrow;endArrow=classic;startArrow=classic;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="69ARyxQlwhHyFWX5DNmJ-7" target="69ARyxQlwhHyFWX5DNmJ-6">
|
||||
<mxGeometry width="100" height="100" relative="1" as="geometry">
|
||||
<mxPoint x="100" y="480" as="sourcePoint" />
|
||||
<mxPoint x="200" y="380" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="69ARyxQlwhHyFWX5DNmJ-19" value="<div>plugin</div>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="440" y="500" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="69ARyxQlwhHyFWX5DNmJ-20" value="<div>KafkaJS</div>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="650" y="250" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="69ARyxQlwhHyFWX5DNmJ-21" value="Multiple clients" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="120" y="170" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
|
@ -16,9 +16,11 @@
|
|||
"express-session": "^1.18.1",
|
||||
"jimp": "^1.6.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"kafkajs": "^2.2.4",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"pg": "^8.13.1",
|
||||
"pug": "^3.0.3"
|
||||
"pug": "^3.0.3",
|
||||
"ws": "^8.18.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.1.9"
|
||||
|
@ -1885,6 +1887,15 @@
|
|||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/kafkajs": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/kafkajs/-/kafkajs-2.2.4.tgz",
|
||||
"integrity": "sha512-j/YeapB1vfPT2iOIUn/vxdyKEuhuY2PxMBvf5JWux6iSaukAccrMtXEY/Lb7OvavDhOWME589bpLrEdnVHjfjA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.includes": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
|
||||
|
@ -3367,6 +3378,27 @@
|
|||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.18.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
|
||||
"integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
|
||||
"license": "MIT",
|
||||
"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/xml-parse-from-string": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz",
|
||||
|
|
|
@ -27,9 +27,11 @@
|
|||
"express-session": "^1.18.1",
|
||||
"jimp": "^1.6.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"kafkajs": "^2.2.4",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"pg": "^8.13.1",
|
||||
"pug": "^3.0.3"
|
||||
"pug": "^3.0.3",
|
||||
"ws": "^8.18.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.1.9"
|
||||
|
|
|
@ -62,7 +62,7 @@ canvas {
|
|||
padding-left: 3%;
|
||||
padding-right: 3%;
|
||||
margin-top: 0%;
|
||||
border:solid 2px gray;
|
||||
border: solid 2px gray;
|
||||
box-shadow: 0px 20px 150px rgba(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
|
@ -100,3 +100,29 @@ canvas {
|
|||
overflow: scroll;
|
||||
border: black solid
|
||||
}
|
||||
|
||||
.messages-container {
|
||||
width: 100%;
|
||||
height: 75%;
|
||||
border: gray solid;
|
||||
}
|
||||
|
||||
.input-container {
|
||||
width: 100%;
|
||||
height: 5%;
|
||||
}
|
||||
|
||||
#chat-input {
|
||||
width: calc(100% - 150px);
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#send-message-button {
|
||||
float: right;
|
||||
width: 150px;
|
||||
height: 100%;
|
||||
font-size: 15pt;
|
||||
margin: 0;
|
||||
padding: 0
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
$(document).ready(() => {
|
||||
const sendData = async () => {
|
||||
alert(1);
|
||||
}
|
||||
|
||||
$("#send-message-button").click(sendData);
|
||||
|
||||
$('#chat-input').keyup(function(e){
|
||||
if(e.keyCode == 13)
|
||||
{
|
||||
$(this).trigger("enterKey");
|
||||
}
|
||||
});
|
||||
|
||||
$("#chat-input").bind("enterKey", sendData);
|
||||
});
|
|
@ -31,7 +31,8 @@ class UserController {
|
|||
utils.removeFromFile('./inviteTokens.txt', req.body.inviteToken);
|
||||
}
|
||||
|
||||
req.session.jwt = jwt.sign({ username }, process.env.SECRET, {expiresIn: "1y"});
|
||||
const token = jwt.sign({ username }, process.env.SECRET, {expiresIn: "1y"});
|
||||
res.cookie("jwt", token);
|
||||
return res.status(200).send("Ok");
|
||||
}
|
||||
|
||||
|
@ -43,12 +44,13 @@ class UserController {
|
|||
if (!bcrypt.compareSync(password, storedPassword)) {
|
||||
return res.status(403).send("Password is not correct");
|
||||
}
|
||||
req.session.jwt = jwt.sign({ username }, process.env.SECRET, {expiresIn: "1y"});
|
||||
const token = jwt.sign({ username }, process.env.SECRET, {expiresIn: "1y"});
|
||||
res.cookie("jwt", token);
|
||||
return res.status(200).send("Ok");
|
||||
}
|
||||
|
||||
async changePassword(req, res) {
|
||||
const token = req.session.jwt;
|
||||
const token = req.cookies["jwt"];
|
||||
const username = jwt.decode(token).username;
|
||||
const { oldPassword, newPassword } = req.body;
|
||||
|
||||
|
@ -67,11 +69,12 @@ class UserController {
|
|||
|
||||
async logout(req, res) {
|
||||
req.session.destroy();
|
||||
res.clearCookie("jwt");
|
||||
return res.redirect("/login");
|
||||
}
|
||||
|
||||
async uploadSkin(req, res) {
|
||||
const token = req.session.jwt;
|
||||
const token = req.cookies["jwt"];
|
||||
const decoded = jwt.decode(token);
|
||||
const tempPath = req.file.path;
|
||||
const targetPath = `/opt/skins/${decoded.username}.png`;
|
||||
|
@ -93,7 +96,7 @@ class UserController {
|
|||
}
|
||||
|
||||
async uploadCape(req, res) {
|
||||
const token = req.session.jwt;
|
||||
const token = req.cookies["jwt"];
|
||||
const decoded = jwt.decode(token);
|
||||
const tempPath = req.file.path;
|
||||
const targetPath = `/opt/cloaks/${decoded.username}.png`;
|
||||
|
@ -116,7 +119,7 @@ class UserController {
|
|||
}
|
||||
|
||||
async getUsername(req, res) {
|
||||
const token = req.session.jwt;
|
||||
const token = req.cookies["jwt"];
|
||||
return res.status(200).send(jwt.decode(token).username);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import UserRouter from './routers/user.js';
|
|||
|
||||
const app = express();
|
||||
|
||||
dotenv.config({path: ".env"});
|
||||
dotenv.config({ path: ".env" });
|
||||
|
||||
app.use(session({
|
||||
secret: process.env.SECRET,
|
||||
|
@ -18,7 +18,7 @@ app.use(session({
|
|||
cookie: { maxAge: 1000 * 60 * 60 * 24 }
|
||||
}));
|
||||
app.use(express.static(path.join('./public')));
|
||||
app.use(express.urlencoded({extended: false}));
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
app.use(express.json());
|
||||
app.use(cookieParser());
|
||||
|
||||
|
@ -27,6 +27,8 @@ app.set('view engine', 'pug');
|
|||
app.use('/api', ApiRouter);
|
||||
app.use('/', UserRouter);
|
||||
|
||||
app.listen(process.env.PORT, () => {
|
||||
const server = app.listen(process.env.PORT, () => {
|
||||
console.log("App has been started!");
|
||||
});
|
||||
|
||||
export default server;
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
import { Kafka } from "kafkajs";
|
||||
import ws from 'ws';
|
||||
import jwt from 'jwt';
|
||||
|
||||
import server from './index.js';
|
||||
|
||||
const kafka = new Kafka({
|
||||
clientId: 'backend',
|
||||
brokers: ['kafka:9092']
|
||||
});
|
||||
|
||||
const wsClients = [];
|
||||
|
||||
const producer = kafka.producer();
|
||||
const consumer = kafka.consumer();
|
||||
|
||||
await producer.connect();
|
||||
await consumer.connect();
|
||||
await consumer.subscribe({
|
||||
topic: "chatMessage",
|
||||
fromBeginning: true
|
||||
});
|
||||
|
||||
const onMessageFromServer = async ({ topic, partition, message }) => {
|
||||
wsClients.forEach(client => {
|
||||
client.send({
|
||||
message
|
||||
})
|
||||
})
|
||||
};
|
||||
|
||||
await consumer.run({
|
||||
eachMessage: onMessageFromServer
|
||||
});
|
||||
|
||||
const wsServer = new ws.Server({ noServer: true });
|
||||
wsServer.on('connection', socket => {
|
||||
wsClients.push(socket);
|
||||
socket.on('message', async (message) => {
|
||||
|
||||
const token = message.jwt;
|
||||
if (!jwt.verify(token, process.env.secret)) {
|
||||
socket.send("JWT is not valid.")
|
||||
return;
|
||||
}
|
||||
|
||||
await producer.send({
|
||||
topic: 'chatMessage',
|
||||
messages: [{
|
||||
author: message.author,
|
||||
content: message.content,
|
||||
date: message.date
|
||||
}]
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('close', async () => {
|
||||
wsClients = wsClients.filter(s => s !== socket);
|
||||
await producer.disconnect();
|
||||
});
|
||||
});
|
||||
|
||||
server.on('upgrade', (request, socket, head) => {
|
||||
wsServer.handleUpgrade(request, socket, head, socket => {
|
||||
wsServer.emit('connection', socket, request);
|
||||
})
|
||||
})
|
||||
|
|
@ -7,9 +7,10 @@ import UserService from '../services/user.js';
|
|||
dotenv.config({path: ".env"});
|
||||
|
||||
const authenticate = async (req, res, next) => {
|
||||
const token = req.session.jwt;
|
||||
const token = req.cookies["jwt"];
|
||||
if (!token || !jwt.verify(token, process.env.SECRET)) {
|
||||
req.session.destroy();
|
||||
res.clearCookie("jwt");
|
||||
return res.redirect("/login");
|
||||
}
|
||||
next();
|
||||
|
@ -33,7 +34,7 @@ const validateInviteToken = async (req, res, next) => {
|
|||
};
|
||||
|
||||
const canHaveCloak = async (req, res, next) => {
|
||||
const { username } = jwt.decode(req.session.jwt);
|
||||
const { username } = jwt.decode(req.cookies["jwt"]);
|
||||
if (!(await UserService.canHaveCloak(username)))
|
||||
return res.status(403).send("You cannot have cloak");
|
||||
next();
|
||||
|
|
|
@ -19,11 +19,11 @@ const userExist = async (req, res, next) => {
|
|||
let username;
|
||||
if (req.body.username) {
|
||||
username = req.body.username;
|
||||
} else if (req.session.jwt) {
|
||||
if (!req.session.jwt || !jwt.verify(req.session.jwt, process.env.SECRET)) {
|
||||
} else if (req.cookies["jwt"]) {
|
||||
if (!req.cookies["jwt"] || !jwt.verify(req.cookies["jwt"], process.env.SECRET)) {
|
||||
return res.status(403).send("Unauthorized");
|
||||
}
|
||||
username = jwt.decode(req.session.jwt).username;
|
||||
username = jwt.decode(req.cookies["jwt"]).username;
|
||||
}
|
||||
|
||||
if (!(await UserService.exists(username))) {
|
||||
|
|
|
@ -10,7 +10,7 @@ dotenv.config({path: ".env"});
|
|||
const UserRouter = new Router();
|
||||
|
||||
UserRouter.get('/register', async (req, res) => {
|
||||
if (req.session.jwt && jwt.verify(req.session.jwt, process.env.SECRET))
|
||||
if (req.cookies["jwt"] && jwt.verify(req.cookies["jwt"], process.env.SECRET))
|
||||
return res.redirect("/index");
|
||||
|
||||
return res.render("register.pug", {
|
||||
|
@ -19,7 +19,7 @@ UserRouter.get('/register', async (req, res) => {
|
|||
});
|
||||
|
||||
UserRouter.get(['/', '/login'], async (req, res) => {
|
||||
if(req.session.jwt && jwt.verify(req.session.jwt, process.env.SECRET)) {
|
||||
if(req.cookies["jwt"] && jwt.verify(req.cookies["jwt"], process.env.SECRET)) {
|
||||
return res.redirect("/index");
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ UserRouter.get(['/', '/login'], async (req, res) => {
|
|||
});
|
||||
|
||||
UserRouter.get(['/index', '/skin'], auth.authenticate, async (req, res) => {
|
||||
const username = jwt.decode(req.session.jwt).username;
|
||||
const username = jwt.decode(req.cookies["jwt"]).username;
|
||||
|
||||
return res.render('skin.pug', {
|
||||
username: username,
|
||||
|
@ -36,7 +36,7 @@ UserRouter.get(['/index', '/skin'], auth.authenticate, async (req, res) => {
|
|||
});
|
||||
|
||||
UserRouter.get('/changepassword', auth.authenticate, async (req, res) => {
|
||||
const username = jwt.decode(req.session.jwt).username;
|
||||
const username = jwt.decode(req.cookies["jwt"]).username;
|
||||
|
||||
return res.render('changepassword.pug', {
|
||||
can_have_cloak: await UserService.canHaveCloak(username)
|
||||
|
@ -44,7 +44,7 @@ UserRouter.get('/changepassword', auth.authenticate, async (req, res) => {
|
|||
});
|
||||
|
||||
UserRouter.get('/chat', auth.authenticate, async (req, res) => {
|
||||
const username = jwt.decode(req.session.jwt).username;
|
||||
const username = jwt.decode(req.cookies["jwt"]).username;
|
||||
|
||||
return res.render('chat.pug', {
|
||||
can_have_cloak: await UserService.canHaveCloak(username)
|
||||
|
@ -52,7 +52,7 @@ UserRouter.get('/chat', auth.authenticate, async (req, res) => {
|
|||
});
|
||||
|
||||
UserRouter.get('/worldmap', auth.authenticate, async (req, res) => {
|
||||
const username = jwt.decode(req.session.jwt).username;
|
||||
const username = jwt.decode(req.cookies["jwt"]).username;
|
||||
|
||||
return res.render('worldmap.pug', {
|
||||
can_have_cloak: await UserService.canHaveCloak(username)
|
||||
|
|
|
@ -4,6 +4,9 @@ html
|
|||
title Личный кабинет | Чат
|
||||
link(href="css/index.css" rel="stylesheet")
|
||||
body
|
||||
script(src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==" crossorigin="anonymous" referrerpolicy="no-referrer")
|
||||
script(type="text/javascript" src="js/chat.js")
|
||||
|
||||
iframe(name="hiddenFrame" style="position:absolute; top:-1px; left:-1px; width:1px; height:1px;")
|
||||
include header.pug
|
||||
|
||||
|
@ -11,4 +14,8 @@ html
|
|||
div(class="content")
|
||||
h1 Чат
|
||||
div(class="chat-container")
|
||||
p Пока что тут пусто, но скоро будет кое-что интересное!
|
||||
div(class="messages-container")
|
||||
|
||||
div(class="input-container")
|
||||
input(type="text" id="chat-input")
|
||||
button(id="send-message-button") Отправить
|
Loading…
Reference in New Issue