add db base
This commit is contained in:
parent
c895312f7a
commit
8f00e688e0
9 changed files with 352 additions and 33 deletions
10
server/config.example.json
Normal file
10
server/config.example.json
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"port": 38195,
|
||||||
|
"database": {
|
||||||
|
"address": "localhost",
|
||||||
|
"port": 3306,
|
||||||
|
"username": "user",
|
||||||
|
"password": "password",
|
||||||
|
"name": "MultiProbe"
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,16 +2,19 @@ import { createReader, createWriter, Endian } from "bufferstuff";
|
||||||
import { WebSocketServer } from "ws";
|
import { WebSocketServer } from "ws";
|
||||||
import Config from "./objects/Config";
|
import Config from "./objects/Config";
|
||||||
import FunkyArray from "./objects/FunkyArray";
|
import FunkyArray from "./objects/FunkyArray";
|
||||||
import User from "./objects/User";
|
import RemoteUser from "./objects/RemoteUser";
|
||||||
import { MessageType } from "./enums/MessageType";
|
import { MessageType } from "./enums/MessageType";
|
||||||
|
import Database from "./objects/Database";
|
||||||
|
|
||||||
const users = new FunkyArray<string, User>();
|
const users = new FunkyArray<string, RemoteUser>();
|
||||||
|
|
||||||
|
new Database(Config.database.address, Config.database.port, Config.database.username, Config.database.password, Config.database.name);
|
||||||
|
|
||||||
const server = new WebSocketServer({
|
const server = new WebSocketServer({
|
||||||
port: Config.port
|
port: Config.port
|
||||||
}, () => console.log(`Server listening at ${Config.port}`));
|
}, () => console.log(`Server listening at ${Config.port}`));
|
||||||
|
|
||||||
function sendToAllButSelf(user:User, data:Buffer) {
|
function sendToAllButSelf(user:RemoteUser, data:Buffer) {
|
||||||
users.forEach(otherUser => {
|
users.forEach(otherUser => {
|
||||||
if (otherUser.id !== user.id && otherUser.currentURL === user.currentURL) {
|
if (otherUser.id !== user.id && otherUser.currentURL === user.currentURL) {
|
||||||
otherUser.send(data);
|
otherUser.send(data);
|
||||||
|
@ -19,7 +22,7 @@ function sendToAllButSelf(user:User, data:Buffer) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendToAll(user:User, data:Buffer) {
|
function sendToAll(user:RemoteUser, data:Buffer) {
|
||||||
users.forEach(otherUser => {
|
users.forEach(otherUser => {
|
||||||
if (otherUser.currentURL === user.currentURL) {
|
if (otherUser.currentURL === user.currentURL) {
|
||||||
otherUser.send(data);
|
otherUser.send(data);
|
||||||
|
@ -29,7 +32,7 @@ function sendToAll(user:User, data:Buffer) {
|
||||||
|
|
||||||
server.on("connection", (socket) => {
|
server.on("connection", (socket) => {
|
||||||
const myUUID = crypto.randomUUID();
|
const myUUID = crypto.randomUUID();
|
||||||
let user:User;
|
let user:RemoteUser;
|
||||||
|
|
||||||
function closeOrError() {
|
function closeOrError() {
|
||||||
if (users.has(myUUID)) {
|
if (users.has(myUUID)) {
|
||||||
|
@ -60,7 +63,7 @@ server.on("connection", (socket) => {
|
||||||
page = "";
|
page = "";
|
||||||
}
|
}
|
||||||
let lengthOfUsernames = 0;
|
let lengthOfUsernames = 0;
|
||||||
const usersOnPage = new Array<User>();
|
const usersOnPage = new Array<RemoteUser>();
|
||||||
await users.forEach(otherUser => {
|
await users.forEach(otherUser => {
|
||||||
if (otherUser.currentURL === page) {
|
if (otherUser.currentURL === page) {
|
||||||
usersOnPage.push(otherUser);
|
usersOnPage.push(otherUser);
|
||||||
|
@ -71,7 +74,7 @@ server.on("connection", (socket) => {
|
||||||
for (const otherUser of usersOnPage) {
|
for (const otherUser of usersOnPage) {
|
||||||
usersToSend.writeUInt(otherUser.id).writeShortString(otherUser.username).writeFloat(otherUser.cursorX).writeInt(otherUser.cursorY);
|
usersToSend.writeUInt(otherUser.id).writeShortString(otherUser.username).writeFloat(otherUser.cursorX).writeInt(otherUser.cursorY);
|
||||||
}
|
}
|
||||||
user = users.set(myUUID, new User(socket, username, page, rawURL));
|
user = users.set(myUUID, new RemoteUser(socket, username, page, rawURL));
|
||||||
sendToAllButSelf(user, createWriter(Endian.LE, 6 + username.length).writeByte(MessageType.ClientJoined).writeUInt(user.id).writeShortString(username).toBuffer());
|
sendToAllButSelf(user, createWriter(Endian.LE, 6 + username.length).writeByte(MessageType.ClientJoined).writeUInt(user.id).writeShortString(username).toBuffer());
|
||||||
user.send(usersToSend.toBuffer());
|
user.send(usersToSend.toBuffer());
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -6,4 +6,14 @@ export default class Config {
|
||||||
public constructor() { throw new Error("Static Class"); }
|
public constructor() { throw new Error("Static Class"); }
|
||||||
|
|
||||||
public static port:number = config.port;
|
public static port:number = config.port;
|
||||||
|
|
||||||
|
public static database:ConfigDatabase = config.database;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ConfigDatabase {
|
||||||
|
address: string,
|
||||||
|
port: number,
|
||||||
|
username: string,
|
||||||
|
password: string,
|
||||||
|
name: string
|
||||||
}
|
}
|
101
server/objects/Database.ts
Normal file
101
server/objects/Database.ts
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
import { createPool, Pool, RowDataPacket } from "mysql2";
|
||||||
|
|
||||||
|
export type DBInDataType = string | number | null | undefined;
|
||||||
|
|
||||||
|
export default class Database {
|
||||||
|
private connectionPool:Pool;
|
||||||
|
private static readonly CONNECTION_LIMIT = 128;
|
||||||
|
|
||||||
|
public connected:boolean = false;
|
||||||
|
|
||||||
|
public static Instance:Database;
|
||||||
|
|
||||||
|
public constructor(databaseAddress:string, databasePort:number = 3306, databaseUsername:string, databasePassword:string, databaseName:string) {
|
||||||
|
this.connectionPool = createPool({
|
||||||
|
connectionLimit: Database.CONNECTION_LIMIT,
|
||||||
|
host: databaseAddress,
|
||||||
|
port: databasePort,
|
||||||
|
user: databaseUsername,
|
||||||
|
password: databasePassword,
|
||||||
|
database: databaseName
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`DB connection pool created. MAX_CONNECTIONS = ${Database.CONNECTION_LIMIT}`);
|
||||||
|
|
||||||
|
Database.Instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public execute(query:string, data?:Array<DBInDataType>) {
|
||||||
|
return new Promise<boolean>((resolve, reject) => {
|
||||||
|
this.connectionPool.getConnection((err, connection) => {
|
||||||
|
if (err) {
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data == null) {
|
||||||
|
connection.execute(query, (err, result) => {
|
||||||
|
if (err) {
|
||||||
|
connection.release();
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(result !== undefined);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
connection.execute(query, data, (err, result) => {
|
||||||
|
if (err) {
|
||||||
|
connection.release();
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(result !== undefined);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public query(query:string, data?:Array<DBInDataType>) {
|
||||||
|
return new Promise<RowDataPacket[]>((resolve, reject) => {
|
||||||
|
this.connectionPool.getConnection((err, connection) => {
|
||||||
|
if (err) {
|
||||||
|
return reject(err);
|
||||||
|
} else {
|
||||||
|
// Use old query
|
||||||
|
if (data == null) {
|
||||||
|
connection.query<RowDataPacket[]>(query, (err, rows) => {
|
||||||
|
connection.release();
|
||||||
|
if (err) {
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(rows);
|
||||||
|
connection.release();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Use new prepared statements w/ placeholders
|
||||||
|
else {
|
||||||
|
connection.execute<RowDataPacket[]>(query, data, (err, rows) => {
|
||||||
|
connection.release();
|
||||||
|
if (err) {
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(rows);
|
||||||
|
connection.release();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async querySingle(query:string, data?:Array<DBInDataType>) {
|
||||||
|
const dbData = await this.query(query, data);
|
||||||
|
if (dbData != null && dbData.length > 0) {
|
||||||
|
return dbData[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
29
server/objects/RemoteUser.ts
Normal file
29
server/objects/RemoteUser.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import { WebSocket } from "ws";
|
||||||
|
|
||||||
|
export default class RemoteUser {
|
||||||
|
private static USER_IDS = 0;
|
||||||
|
|
||||||
|
private readonly socket:WebSocket;
|
||||||
|
public readonly id:number;
|
||||||
|
public readonly username:string;
|
||||||
|
public readonly currentURL:string;
|
||||||
|
public readonly rawURL:string = "";
|
||||||
|
public cursorX:number = 0;
|
||||||
|
public cursorY:number = 0;
|
||||||
|
public allowedPings:number;
|
||||||
|
public lastPingReset:number;
|
||||||
|
|
||||||
|
constructor(socket:WebSocket, username:string, currentURL:string, rawURL:string) {
|
||||||
|
this.socket = socket;
|
||||||
|
this.id = RemoteUser.USER_IDS++;
|
||||||
|
this.username = username;
|
||||||
|
this.currentURL = currentURL;
|
||||||
|
this.rawURL = rawURL;
|
||||||
|
this.allowedPings = 10;
|
||||||
|
this.lastPingReset = Date.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
send(data:Buffer) {
|
||||||
|
this.socket.send(data);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,29 +1,41 @@
|
||||||
import { WebSocket } from "ws";
|
|
||||||
|
|
||||||
export default class User {
|
export default class User {
|
||||||
private static USER_IDS = 0;
|
public Id:number;
|
||||||
|
public Username:string;
|
||||||
|
public PasswordSalt:string;
|
||||||
|
public PasswordHash:string;
|
||||||
|
public CreatedByUserId:number;
|
||||||
|
public CreatedDatetime:Date;
|
||||||
|
public LastModifiedByUserId:number;
|
||||||
|
public LastModifiedDatetime:Date;
|
||||||
|
public DeletedByUserId:number;
|
||||||
|
public DeletedDatetime:Date;
|
||||||
|
public IsDeleted:boolean;
|
||||||
|
|
||||||
private readonly socket:WebSocket;
|
public constructor(id?:number, username?:string, passwordSalt?:string, passwordHash?:string, createdByUserId?:number, createdDateTime?:Date, lastModifiedByUserId?:number, lastModifiedDatetime?:Date, deletedByUserId?:number, deletedDatetime?:Date, isDeleted?:boolean) {
|
||||||
public readonly id:number;
|
if (typeof(id) == "number" && typeof(username) == "string" && typeof(passwordHash) == "string" && typeof(passwordSalt) == "string" && typeof(createdByUserId) == "number" && createdDateTime instanceof Date && typeof(lastModifiedByUserId) == "number" && lastModifiedDatetime instanceof Date && typeof(deletedByUserId) == "number" && deletedDatetime instanceof Date && typeof(isDeleted) == "boolean") {
|
||||||
public readonly username:string;
|
this.Id = id;
|
||||||
public readonly currentURL:string;
|
this.Username = username;
|
||||||
public readonly rawURL:string = "";
|
this.PasswordHash = passwordHash;
|
||||||
public cursorX:number = 0;
|
this.PasswordSalt = passwordSalt;
|
||||||
public cursorY:number = 0;
|
this.CreatedByUserId = createdByUserId;
|
||||||
public allowedPings:number;
|
this.CreatedDatetime = createdDateTime;
|
||||||
public lastPingReset:number;
|
this.LastModifiedByUserId = lastModifiedByUserId;
|
||||||
|
this.LastModifiedDatetime = lastModifiedDatetime;
|
||||||
constructor(socket:WebSocket, username:string, currentURL:string, rawURL:string) {
|
this.DeletedByUserId = deletedByUserId;
|
||||||
this.socket = socket;
|
this.DeletedDatetime = deletedDatetime;
|
||||||
this.id = User.USER_IDS++;
|
this.IsDeleted = isDeleted;
|
||||||
this.username = username;
|
} else {
|
||||||
this.currentURL = currentURL;
|
this.Id = Number.MIN_VALUE;
|
||||||
this.rawURL = rawURL;
|
this.Username = "";
|
||||||
this.allowedPings = 10;
|
this.PasswordHash = "";
|
||||||
this.lastPingReset = Date.now();
|
this.PasswordSalt = "";
|
||||||
|
this.CreatedByUserId = Number.MIN_VALUE;
|
||||||
|
this.CreatedDatetime = new Date(0);
|
||||||
|
this.LastModifiedByUserId = Number.MIN_VALUE;
|
||||||
|
this.LastModifiedDatetime = new Date(0);
|
||||||
|
this.DeletedByUserId = Number.MIN_VALUE;
|
||||||
|
this.DeletedDatetime = new Date(0);
|
||||||
|
this.IsDeleted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
send(data:Buffer) {
|
|
||||||
this.socket.send(data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
101
server/package-lock.json
generated
101
server/package-lock.json
generated
|
@ -10,6 +10,7 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bufferstuff": "^1.5.1",
|
"bufferstuff": "^1.5.1",
|
||||||
|
"mysql2": "^3.9.7",
|
||||||
"ws": "^8.16.0"
|
"ws": "^8.16.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -539,6 +540,14 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/denque": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/diff": {
|
"node_modules/diff": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
||||||
|
@ -761,6 +770,14 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/generate-function": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"is-property": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/get-intrinsic": {
|
"node_modules/get-intrinsic": {
|
||||||
"version": "1.2.4",
|
"version": "1.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
|
||||||
|
@ -929,6 +946,17 @@
|
||||||
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
|
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/iconv-lite": {
|
||||||
|
"version": "0.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||||
|
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||||
|
"dependencies": {
|
||||||
|
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ignore-by-default": {
|
"node_modules/ignore-by-default": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
|
||||||
|
@ -1122,6 +1150,11 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-property": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="
|
||||||
|
},
|
||||||
"node_modules/is-regex": {
|
"node_modules/is-regex": {
|
||||||
"version": "1.1.4",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
|
||||||
|
@ -1243,6 +1276,11 @@
|
||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/long": {
|
||||||
|
"version": "5.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
|
||||||
|
"integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
|
||||||
|
},
|
||||||
"node_modules/lru-cache": {
|
"node_modules/lru-cache": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||||
|
@ -1282,6 +1320,51 @@
|
||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mysql2": {
|
||||||
|
"version": "3.9.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.9.7.tgz",
|
||||||
|
"integrity": "sha512-KnJT8vYRcNAZv73uf9zpXqNbvBG7DJrs+1nACsjZP1HMJ1TgXEy8wnNilXAn/5i57JizXKtrUtwDB7HxT9DDpw==",
|
||||||
|
"dependencies": {
|
||||||
|
"denque": "^2.1.0",
|
||||||
|
"generate-function": "^2.3.1",
|
||||||
|
"iconv-lite": "^0.6.3",
|
||||||
|
"long": "^5.2.1",
|
||||||
|
"lru-cache": "^8.0.0",
|
||||||
|
"named-placeholders": "^1.1.3",
|
||||||
|
"seq-queue": "^0.0.5",
|
||||||
|
"sqlstring": "^2.3.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mysql2/node_modules/lru-cache": {
|
||||||
|
"version": "8.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz",
|
||||||
|
"integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/named-placeholders": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==",
|
||||||
|
"dependencies": {
|
||||||
|
"lru-cache": "^7.14.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/named-placeholders/node_modules/lru-cache": {
|
||||||
|
"version": "7.18.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
|
||||||
|
"integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/nice-try": {
|
"node_modules/nice-try": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
|
||||||
|
@ -1629,6 +1712,11 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/safer-buffer": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "7.6.0",
|
"version": "7.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
|
||||||
|
@ -1644,6 +1732,11 @@
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/seq-queue": {
|
||||||
|
"version": "0.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
|
||||||
|
"integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
|
||||||
|
},
|
||||||
"node_modules/set-function-length": {
|
"node_modules/set-function-length": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
||||||
|
@ -1787,6 +1880,14 @@
|
||||||
"integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==",
|
"integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/sqlstring": {
|
||||||
|
"version": "2.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
|
||||||
|
"integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/string.prototype.padend": {
|
"node_modules/string.prototype.padend": {
|
||||||
"version": "3.1.6",
|
"version": "3.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz",
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bufferstuff": "^1.5.1",
|
"bufferstuff": "^1.5.1",
|
||||||
|
"mysql2": "^3.9.7",
|
||||||
"ws": "^8.16.0"
|
"ws": "^8.16.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
52
server/repos/UserRepo.ts
Normal file
52
server/repos/UserRepo.ts
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import Database from "../objects/Database";
|
||||||
|
import User from "../objects/User";
|
||||||
|
|
||||||
|
export default class UsersRepo {
|
||||||
|
public static async selectById(id:number) {
|
||||||
|
const dbUser = await Database.Instance.query("SELECT * FROM User WHERE Id = ? LIMIT 1", [id]);
|
||||||
|
if (dbUser == null || dbUser.length === 0) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
const user = new User();
|
||||||
|
populateUserFromDB(user, dbUser[0]);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async selectByUsername(username:string) {
|
||||||
|
const dbUser = await Database.Instance.query("SELECT * FROM User WHERE Username = ? LIMIT 1", [username]);
|
||||||
|
if (dbUser == null || dbUser.length === 0) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
const user = new User();
|
||||||
|
populateUserFromDB(user, dbUser[0]);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async insertUpdate(user:User) {
|
||||||
|
if (user.Id === Number.MIN_VALUE) {
|
||||||
|
await Database.Instance.query("INSERT users (Username, PasswordHash, PasswordSalt, CreatedByUserId, CreatedDatetime, LastModifiedByUserId, LastModifiedDatetime, DeletedByUserId, DeletedDatetime, IsDeleted) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [
|
||||||
|
user.Username, user.PasswordHash, user.PasswordSalt, user.CreatedByUserId, user.CreatedDatetime.getTime(), user.LastModifiedByUserId, user.LastModifiedDatetime.getTime(), user.DeletedByUserId, user.DeletedDatetime.getTime(), Number(user.IsDeleted)
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
await Database.Instance.query(`UPDATE users SET Username = ?, PasswordHash = ?, PasswordSalt = ?, CreatedByUserId = ?, CreatedDatetime = ?, LastModifiedByUserId = ?, LastModifiedDatetime = ?, DeletedByUserId = ?, DeletedDatetime = ?, IsDeleted = ?, WHERE Id = ?`, [
|
||||||
|
user.Username, user.PasswordHash, user.PasswordSalt, user.CreatedByUserId, user.CreatedDatetime.getTime(), user.LastModifiedByUserId, user.LastModifiedDatetime.getTime(), user.DeletedByUserId, user.DeletedDatetime.getTime(), Number(user.IsDeleted), user.Id
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function populateUserFromDB(user:User, dbUser:any) {
|
||||||
|
user.Id = dbUser.Id;
|
||||||
|
user.Username = dbUser.Username;
|
||||||
|
user.PasswordHash = dbUser.PasswordHash;
|
||||||
|
user.PasswordSalt = dbUser.PasswordSalt;
|
||||||
|
user.CreatedByUserId = dbUser.CreatedByUserId;
|
||||||
|
user.CreatedDatetime = dbUser.CreatedDatetime;
|
||||||
|
user.LastModifiedByUserId = dbUser.LastModifiedByUserId;
|
||||||
|
user.LastModifiedDatetime = dbUser.LastModifiedDatetime;
|
||||||
|
user.DeletedByUserId = dbUser.DeletedByUserId;
|
||||||
|
user.DeletedDatetime = dbUser.DeletedDatetime;
|
||||||
|
user.IsDeleted = dbUser.IsDeleted;
|
||||||
|
}
|
Loading…
Reference in a new issue