Skip to content

Commit

Permalink
Merge pull request #49 from stzups/temp
Browse files Browse the repository at this point in the history
v0.3.4 Bugfixes, improve db creation, improve exceptions, overhaul config
  • Loading branch information
griffinht authored Apr 5, 2021
2 parents 36adce1 + 4095b92 commit 510de40
Show file tree
Hide file tree
Showing 91 changed files with 1,012 additions and 557 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,13 @@ Rework db, implement document persistence

- Canvas is saved in db
- Rework user authentication

### v0.3.4
Document update/delete operations, overhaul db and config

- Fix changes not being saved on canvas close
- Fix canvas serialization
- Fix connected clients list
- Add db creation scripts into version control
- Overhaul config - improve exceptions
- Add document update and delete functionality
2 changes: 2 additions & 0 deletions board-database/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FROM postgres
COPY init.sql /docker-entrypoint-initdb.d/
43 changes: 43 additions & 0 deletions board-database/init.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
CREATE DATABASE board;

-- Connect to board database (currently on default postgres database)
\c board
REVOKE CONNECT ON DATABASE board FROM PUBLIC;
REVOKE ALL ON SCHEMA public FROM PUBLIC;

CREATE USER board_room PASSWORD 'changeme';
GRANT CONNECT ON DATABASE board TO board_room;
GRANT USAGE ON SCHEMA public TO board_room;

-- Create tables and grant permissions
CREATE TABLE users(
id bigint NOT NULL,
owned_documents bigint[] NOT NULL,
shared_documents bigint[] NOT NULL,
PRIMARY KEY (id)
);
GRANT SELECT, INSERT, UPDATE ON users TO board_room;

CREATE TABLE documents(
id bigint NOT NULL,
owner bigint NOT NULL,
name varchar(64) not null,
PRIMARY KEY (id)
);
GRANT SELECT, INSERT, UPDATE, DELETE ON documents TO board_room;

CREATE TABLE canvases(
document bigint NOT NULL,
data bytea NOT NULL,
PRIMARY KEY (document)
);
GRANT SELECT, INSERT, UPDATE, DELETE ON canvases TO board_room;

CREATE TABLE persistent_user_sessions(
id bigint NOT NULL,
"user" bigint NOT NULL,
creation_time timestamp,
hashed_token bytea NOT NULL,
PRIMARY KEY (id)
);
GRANT SELECT, INSERT, DELETE ON persistent_user_sessions TO board_room;
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import ClientMessageOpenDocument from "./protocol/client/messages/ClientMessageO
import ClientMessageCreateDocument from "./protocol/client/messages/ClientMessageCreateDocument.js";
import ClientMessageHandshake from "./protocol/client/messages/ClientMessageHandshake.js";
import ServerMessageType from "./protocol/server/ServerMessageType.js";
import WebSocketHandlerType from "./protocol/WebSocketHandlerType.js";
import ClientMessageUpdateCanvas from "./protocol/client/messages/ClientMessageUpdateCanvas.js";
import Shape from "./canvas/canvasObjects/Shape.js";
import {CanvasObjectType} from "./canvas/CanvasObjectType.js";
import CanvasObjectWrapper from "./canvas/CanvasObjectWrapper.js";
import SocketEventType from "./protocol/SocketEventType.js";

const documents = new Map();
let activeDocument = null;
Expand All @@ -29,7 +29,7 @@ class Document {
activeDocument = this;
activeDocument.open();

socket.send(new ClientMessageOpenDocument(this.id));
socket.send(new ClientMessageOpenDocument(this));
} else {
console.log('id was null', this);
}
Expand All @@ -49,7 +49,7 @@ class Document {
}

close() {
//localClient.update();
localUpdate();
ctx.clearRect(0, 0, canvas.width, canvas.height);//todo a loading screen?
this.clients.forEach((client) => {
this.removeClient(client.id);
Expand Down Expand Up @@ -99,32 +99,34 @@ function draw(now) {
}
window.requestAnimationFrame(draw);

socket.addMessageListener(ServerMessageType.ADD_CLIENT, (event) => {
let client = new Client(event.id, User.getUser(event.userId));
activeDocument.addClient(client);
console.log('Add client ', client);
socket.addMessageListener(ServerMessageType.ADD_CLIENT, (serverMessageAddClient) => {
serverMessageAddClient.clients.forEach((value) => {
let client = new Client(value.id, User.getUser(value.userId));
activeDocument.addClient(client);
console.log('Add client ', client);
})
});
socket.addMessageListener(ServerMessageType.REMOVE_CLIENT, (event) => {
console.log('Remove client ', activeDocument.removeClient(event.id));
socket.addMessageListener(ServerMessageType.REMOVE_CLIENT, (serverMessageRemoveClient) => {
console.log('Remove client ', activeDocument.removeClient(serverMessageRemoveClient.id));
});
socket.addMessageListener(ServerMessageType.UPDATE_CANVAS, (event) => {
socket.addMessageListener(ServerMessageType.UPDATE_CANVAS, (serverMessageUpdateCanvas) => {
if (activeDocument != null) {
activeDocument.canvas.updateMultiple(event.canvasObjectWrappers);
activeDocument.canvas.updateMultiple(serverMessageUpdateCanvas.canvasObjectWrappers);
} else {
console.warn('oops');
}
});
socket.addMessageListener(ServerMessageType.ADD_DOCUMENT, (event) => {
documents.set(event.id, new Document(event.name, event.id));
socket.addMessageListener(ServerMessageType.UPDATE_DOCUMENT, (serverMessageUpdateDocument) => {
documents.set(serverMessageUpdateDocument.id, new Document(serverMessageUpdateDocument.name, serverMessageUpdateDocument.id));
});
socket.addMessageListener(ServerMessageType.HANDSHAKE, (event) => {
window.localStorage.setItem('id', event.id.toString());
window.localStorage.setItem('token', event.token.toString());
socket.addMessageListener(ServerMessageType.HANDSHAKE, (serverMessageHandshake) => {
window.localStorage.setItem('id', serverMessageHandshake.id.toString());
window.localStorage.setItem('token', serverMessageHandshake.token.toString());
})
socket.addMessageListener(ServerMessageType.OPEN_DOCUMENT, (event) => {
activeDocument.canvas = event.canvas;
socket.addMessageListener(ServerMessageType.OPEN_DOCUMENT, (serverMessageOpenDocument) => {
activeDocument.canvas = serverMessageOpenDocument.canvas;
})
socket.addEventListener(WebSocketHandlerType.OPEN, () => {
socket.addEventListener(SocketEventType.OPEN, () => {
let id = window.localStorage.getItem('id');
if (id != null) {
id = BigInt(id);
Expand Down Expand Up @@ -159,13 +161,14 @@ const MAX_TIME = 2000;
const UPDATE_INTERVAL = 1000;
let lastUpdate = 0;
let updateCanvas = new Canvas();
setInterval(() => {
setInterval(localUpdate, UPDATE_INTERVAL);
function localUpdate() {
lastUpdate = window.performance.now();
if (updateCanvas.updateCanvasObjects.size > 0) {
socket.send(new ClientMessageUpdateCanvas(updateCanvas.updateCanvasObjects));//todo breaks the server when the size is 0
updateCanvas.updateCanvasObjects.clear();
}
}, UPDATE_INTERVAL);
}

function getDt() {
return (window.performance.now() - lastUpdate) / MAX_TIME * 255;
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ class User {
}
}

socket.addMessageListener(ServerMessageType.HANDSHAKE, (event) => {
user = new User(event.userId);
socket.addMessageListener(ServerMessageType.HANDSHAKE, (serverMessageHandshake) => {
user = new User(serverMessageHandshake.userId);
})
socket.addMessageListener(ServerMessageType.ADD_USER, (event) => {
let user = users.get(event.user.id);
socket.addMessageListener(ServerMessageType.ADD_USER, (serverMessageAddUser) => {
let user = users.get(serverMessageAddUser.user.id);
if (user == null) {
user = new User(event.user.id);
user = new User(serverMessageAddUser.user.id);
}
Object.assign(user, event.user);
Object.assign(user, serverMessageAddUser.user);
});
File renamed without changes.
File renamed without changes.
5 changes: 5 additions & 0 deletions board-frontend/html/scripts/protocol/SocketEventType.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
let SocketEventType;
export default SocketEventType = {
OPEN:0,
CLOSE:1,
};
90 changes: 90 additions & 0 deletions board-frontend/html/scripts/protocol/WebSocketHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import BufferReader from './BufferReader.js'
import BufferWriter from "./BufferWriter.js";
import ServerMessageType from "./server/ServerMessageType.js";
import SocketEventType from "./SocketEventType.js";
import {getServerMessage} from "./server/ServerMessageType.js";

const HTTP_PORT = 8080;
const HTTPS_PORT = 443;

class WebSocketHandler {
constructor() {
this.socketEvents = {};
Object.keys(SocketEventType).forEach((key, value) => {
this.socketEvents[value] = [];
});

this.serverMessageEvents = {};
Object.keys(ServerMessageType).forEach((key, value) => {
this.serverMessageEvents[value] = [];
});

let webSocketUrl;
if (window.location.protocol === 'https:') {
webSocketUrl = 'wss://localhost:' + HTTPS_PORT + '/websocket';
} else {
console.warn('Insecure connection, this better be a development environment');//todo disable/disallow
webSocketUrl = 'ws://localhost:' + HTTP_PORT + '/websocket';
}
console.log('Opening WebSocket connection to ' + webSocketUrl);
this.socket = new WebSocket(webSocketUrl);
this.socket.binaryType = 'arraybuffer';

this.socket.addEventListener('open', (event) => {
console.log('WebSocket connection opened');
this.dispatchEvent(SocketEventType.OPEN);
});

this.socket.addEventListener('close', (event) => {
console.log('WebSocket connection closed');
this.dispatchEvent(SocketEventType.CLOSE);
});

this.socket.addEventListener('message', (event) => {
console.warn('recv');
if (typeof event.data === 'string') {
console.log(event.data);
} else {
let reader = new BufferReader(event.data);
while (reader.hasNext()) {
this.dispatchMessageEvent(getServerMessage(reader.readUint8(), reader));
}
}
});

this.socket.addEventListener('error', (event) => {
console.error('socket error', event);
});
}

addEventListener(socketEventType, onSocketEvent) {
this.socketEvents[socketEventType].push(onSocketEvent);
}

dispatchEvent(socketEventType, socketEvent) {
console.log('recv', socketEventType, socketEvent);
this.socketEvents[socketEventType].forEach(onSocketEvent => onSocketEvent(socketEvent));
}

addMessageListener(serverMessageType, onServerMessage) {
this.serverMessageEvents[serverMessageType].push(onServerMessage);
}

dispatchMessageEvent(serverMessage) {
console.log('recv', serverMessage.type, serverMessage);
this.serverMessageEvents[serverMessage.type].forEach(onServerMessage => onServerMessage(serverMessage));
}

send(message) {
if (this.socket.readyState === WebSocket.OPEN) {
console.log('send', message);
let writer = new BufferWriter(message.getBufferSize());
message.serialize(writer);
this.socket.send(writer.getBuffer());
} else {
console.error('tried to send message while websocket was closed', message);
}
}
}

export default new WebSocketHandler();
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ const ClientMessageType = {
UPDATE_CANVAS:1,
CREATE_DOCUMENT:2,
HANDSHAKE:3,
DELETE_DOCUMENT:4,
UPDATE_DOCUMENT:5
};
export default ClientMessageType;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import ClientMessageType from "../ClientMessageType.js";
import ClientMessage from "../ClientMessage.js";

export default class ClientMessageDeleteDocument extends ClientMessage {
constructor(document) {
super(ClientMessageType.DELETE_DOCUMENT);
this.id = document.id;
}

getBufferSize() {
return super.getBufferSize() + 8;
}

serialize(writer) {
super.serialize(writer);
writer.writeBigInt64(this.id);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import ClientMessageType from "../ClientMessageType.js";
import ClientMessage from "../ClientMessage.js";

export default class ClientMessageOpenDocument extends ClientMessage {
constructor(id) {
constructor(document) {
super(ClientMessageType.OPEN_DOCUMENT);
this.id = id;
this.id = document.id;
}

getBufferSize() {
Expand All @@ -13,7 +13,6 @@ export default class ClientMessageOpenDocument extends ClientMessage {

serialize(writer) {
super.serialize(writer);

writer.writeBigInt64(this.id);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import ClientMessageType from "../ClientMessageType.js";
import ClientMessage from "../ClientMessage.js";

export default class ClientMessageUpdateDocument extends ClientMessage {
constructor(document) {
super(ClientMessageType.UPDATE_DOCUMENT);
this.id = document.id;
this.name = document.name;
}

getBufferSize() {
return super.getBufferSize() + 8;
}

serialize(writer) {
super.serialize(writer);
writer.writeBigInt64(this.id);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ export default class ServerMessage {
constructor(type) {
this.type = type;
}
}
}
Loading

0 comments on commit 510de40

Please sign in to comment.