Преглед на файлове

feat: added passcode authentication to socket.io, added socket.io status alert

Kristian Vos преди 4 години
родител
ревизия
7cc63d701f

+ 5 - 1
backend/config/template.json

@@ -1,3 +1,7 @@
 {
-	"fancyConsole": true
+	"fancyConsole": true,
+	"mongo": {
+		"url": ""
+	},
+	"passcode": "Secret"
 }

+ 14 - 0
backend/logic/io/index.js

@@ -31,6 +31,20 @@ module.exports = class extends coreClass {
 
 			this.namespaces = require("./namespaces");
 
+			io.use((socket, next) => {
+				const passcode = socket.request._query.passcode;
+				if (passcode === config.get("passcode")) next();
+				else {
+					this.logger.error("IO_MODULE", "Blocked unauthorized user from connecting.");
+					let error = new Error();
+					error.data = {
+						type: "CONNECT_ERROR",
+						message: "Not authorized."
+					};
+					next(error);
+				}
+			});
+
 			io.on('connection', (socket) => {
 				console.log('a user connected');
 

+ 12 - 1
frontend/io.js

@@ -62,7 +62,10 @@ export default {
 	},
 
 	init(url) {
-		this.socket = window.socket = io(url);
+		const passcode = localStorage.getItem("passcode") || "";
+		this.socket = window.socket = io(url, {
+			query: `passcode=${passcode}`
+		});
 
 		this.socket.on("connect", () => {
 			callbacks.onConnect.temp.forEach(cb => cb());
@@ -81,6 +84,14 @@ export default {
 			callbacks.onConnectError.persist.forEach(cb => cb());
 		});
 
+		this.socket.on("error", err => {
+			console.log("IO: SOCKET ERROR");
+			if (err.type && err.type === "CONNECT_ERROR") {
+				callbacks.onConnectError.temp.forEach(cb => cb());
+				callbacks.onConnectError.persist.forEach(cb => cb());
+			}
+		});
+
 		this.ready = true;
 
 		callbacks.general.temp.forEach(callback => callback(this.socket));

+ 4 - 0
frontend/main.js

@@ -27,6 +27,10 @@ const router = new VueRouter({
 			path: "/schemas",
 			component: () => import("./vue/pages/Schemas.vue")
 		},
+		{
+			path: "/options",
+			component: () => import("./vue/pages/Options.vue")
+		},
 		{
 			path: "/schemas/:schemaId",
 			component: () => import("./vue/pages/ViewSchema.vue")

+ 36 - 2
frontend/vue/App.vue

@@ -2,20 +2,41 @@
 	<div>
 		<navbar/>
 		<router-view />
+		<span v-if="connecting" class="alert">Socket.io connecting</span>
+		<span v-if="!connecting && !connected" class="alert">Socket.io not connected</span>
 	</div>
 </template>
 
 <script>
+import io from "../io.js";
+
 import Navbar from './components/Navbar.vue';
 
 export default {
 	components: { Navbar },
 	replace: false,
+	data: () => {
+		return {
+			connecting: true,
+			connected: false
+		}
+	},
 	methods: {
 		
 	},
 	mounted() {
-		
+		io.onConnect(() => {
+			this.connected = true;
+			this.connecting = false
+		});
+
+		io.onDisconnect(() => {
+			this.connected = false;
+		});
+
+		io.onConnectError(() => {
+			this.connecting = false;
+		});
 	}
 };
 </script>
@@ -43,6 +64,11 @@ main {
 	display: inline-block;
 	box-shadow: none;
 	border: none;
+	cursor: pointer;
+
+	&:hover, &:focus {
+		background-color: rgb(22, 133, 170);
+	}
 }
 
 input {
@@ -51,5 +77,13 @@ input {
 </style>
 
 <style lang="scss" scoped>
-
+.alert {
+	position: absolute;
+	top: 50px;
+	right: 50px;
+	background-color: rgb(45, 150, 185);
+	color: white;
+	padding: 20px;
+	font-size: 40px;
+}
 </style>

+ 1 - 1
frontend/vue/components/AccountForm.vue

@@ -11,7 +11,7 @@
 			:key="field.fieldId"
 			:ref="field.fieldId"
 			:fieldTypes="field.fieldTypes"/>
-			<button @click="submit()" type="button">
+			<button @click="submit()" type="button" class="button">
 				Submit
 			</button>
 	</form>

+ 5 - 0
frontend/vue/components/Navbar.vue

@@ -15,6 +15,11 @@
 				Schemas
 			</a>
 		</router-link>
+		<router-link to="/options" v-slot="{ href, navigate, isExactActive }">
+			<a :class="{ 'active': isExactActive }" :href="href" @click="navigate">
+				Options
+			</a>
+		</router-link>
 	</navbar>
 </template>
 

+ 38 - 0
frontend/vue/pages/Options.vue

@@ -0,0 +1,38 @@
+<template>
+	<main>
+		<h1>Options</h1>
+		<hr/>
+		<br/>
+		<div class="control">
+			<label for="passcode">Passcode: </label>
+			<input type="text" id="passcode" v-model="passcode"/>
+		</div>
+		<button class="button" @click="save()">Save</button>
+	</main>
+</template>
+
+<script>
+export default {
+	components: {  },
+	data: () => {
+		return {
+			passcode: ""
+		}
+	},
+	computed: {
+		
+	},
+	methods: {
+		save() {
+			localStorage.setItem("passcode", this.passcode);
+		}
+	},
+	mounted() {
+		this.passcode = localStorage.getItem("passcode");
+	}
+};
+</script>
+
+<style lang="scss" scoped>
+
+</style>