mirror of
https://github.com/Discreetly/server.git
synced 2026-04-17 03:00:55 -04:00
chore(code reorg) segmented code better
This commit is contained in:
45
prisma/seed.js
Normal file
45
prisma/seed.js
Normal file
@@ -0,0 +1,45 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { genId } from 'discreetly-interfaces';
|
||||
import { generateClaimCodes } from 'discreetly-claimcodes';
|
||||
const prisma = new PrismaClient();
|
||||
const idc = genId(0n, "First User").toString();
|
||||
const idc2 = genId(0n, "Second User").toString();
|
||||
const claimCodes = generateClaimCodes(10);
|
||||
// console.log(claimCodes);
|
||||
let codeArr = [];
|
||||
claimCodes.forEach(code => {
|
||||
codeArr.push({ claimcode: code.code });
|
||||
});
|
||||
const seedData = {
|
||||
where: {
|
||||
roomId: genId(0n, "First Room").toString()
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
roomId: genId(0n, "First Room").toString(),
|
||||
name: "First Room",
|
||||
identities: [idc, idc2],
|
||||
claimCodes: {
|
||||
create: codeArr
|
||||
}
|
||||
}
|
||||
};
|
||||
async function main() {
|
||||
await prisma.rooms.upsert(seedData);
|
||||
await prisma.rooms.upsert({
|
||||
where: {
|
||||
roomId: genId(0n, "Room Two").toString()
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
roomId: genId(0n, "Room Two").toString(),
|
||||
name: "Room Two",
|
||||
identities: [idc],
|
||||
claimCodes: {
|
||||
create: codeArr
|
||||
}
|
||||
}
|
||||
});
|
||||
console.log(seedData);
|
||||
}
|
||||
main();
|
||||
@@ -15,7 +15,7 @@ console.log('SERVERID:', serverID);
|
||||
export const serverConfig: ServerI = {
|
||||
id: serverID,
|
||||
name: 'Localhost',
|
||||
serverInfoEndpoint: 'localhost:3001',
|
||||
messageHandlerSocket: 'http://localhost:3002',
|
||||
serverInfoEndpoint: '3001',
|
||||
messageHandlerSocket: '3002',
|
||||
version: '0.0.1'
|
||||
};
|
||||
18
src/data/db.ts
Normal file
18
src/data/db.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { RoomI } from 'discreetly-interfaces';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
export function getRoomByID(id: string): RoomI | null {
|
||||
prisma.rooms
|
||||
.findUnique({
|
||||
where: {
|
||||
roomId: id
|
||||
}
|
||||
})
|
||||
.then((room) => {
|
||||
return room;
|
||||
})
|
||||
.catch((err) => console.error(err));
|
||||
return null;
|
||||
}
|
||||
@@ -1,11 +1,16 @@
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
import { faker } from '@faker-js/faker';
|
||||
import { MessageI } from 'discreetly-interfaces';
|
||||
import { Server as SocketIOServer } from 'socket.io';
|
||||
|
||||
export default function Mock(io: SocketIOServer) {
|
||||
class randomMessagePicker {
|
||||
values: any;
|
||||
weightSums: any[];
|
||||
values: any[];
|
||||
weightSums: number[];
|
||||
constructor(values, weights) {
|
||||
this.values = values;
|
||||
this.weightSums = [];
|
||||
143
src/endpoints/index.ts
Normal file
143
src/endpoints/index.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { serverConfig } from '../config/serverConfig';
|
||||
import { pp } from '../utils.js';
|
||||
import { getRoomByID } from '../data/db';
|
||||
import { genId } from 'discreetly-interfaces';
|
||||
|
||||
// TODO! Properly handle authentication for admin controls
|
||||
// TODO api endpoint that creates new rooms and generates invite codes for them
|
||||
|
||||
export function initEndpoints(app) {
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
app.get(['/', '/api'], (req, res) => {
|
||||
pp('Express: fetching server info');
|
||||
res.json(serverConfig);
|
||||
});
|
||||
|
||||
app.get('/logclaimcodes', () => {
|
||||
pp('Express: fetching claim codes');
|
||||
prisma.claimCodes
|
||||
.findMany()
|
||||
.then((claimCodes) => {
|
||||
console.log(claimCodes);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/api/rooms', (req, res) => {
|
||||
pp(String('Express: fetching all rooms'));
|
||||
prisma.rooms
|
||||
.findMany()
|
||||
.then((rooms) => {
|
||||
res.status(200).json(rooms);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Internal Server Error' });
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/api/rooms/:id', (req, res) => {
|
||||
// TODO This should return the room info for the given room ID
|
||||
pp(String('Express: fetching room info for ' + req.params.id));
|
||||
const room = getRoomByID(req.params.id);
|
||||
if (!room) {
|
||||
res.status(500).json({ error: 'Internal Server Error' });
|
||||
}
|
||||
res.status(200).json(room);
|
||||
});
|
||||
|
||||
app.post('/join', (req, res) => {
|
||||
interface JoinRequestBody {
|
||||
code: string;
|
||||
idc: string;
|
||||
}
|
||||
|
||||
const { code, idc } = req.body as JoinRequestBody;
|
||||
|
||||
pp(`Express[/join]: claiming code: ${code}`);
|
||||
|
||||
prisma.claimCodes
|
||||
.findUnique({
|
||||
where: {
|
||||
claimcode: code
|
||||
}
|
||||
})
|
||||
.then((codeStatus: { claimed: boolean; roomIds: string[] }) => {
|
||||
if (codeStatus.claimed === false) {
|
||||
prisma.claimCodes
|
||||
.update({
|
||||
where: {
|
||||
claimcode: code
|
||||
},
|
||||
data: {
|
||||
claimed: true
|
||||
}
|
||||
})
|
||||
.then((claimCode: { roomIds: string[] }) => {
|
||||
const roomIds = claimCode.roomIds.map((room) => room);
|
||||
prisma.rooms
|
||||
.updateMany({
|
||||
where: {
|
||||
roomId: {
|
||||
in: roomIds
|
||||
}
|
||||
},
|
||||
data: {
|
||||
identities: {
|
||||
push: idc
|
||||
}
|
||||
}
|
||||
})
|
||||
.then((updatedRooms) => {
|
||||
res.status(200).json(updatedRooms);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Internal Server Error' });
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Internal Server Error' });
|
||||
});
|
||||
} else {
|
||||
res.status(400).json({ message: 'Claim code already used' });
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Internal Server Error' });
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/room/add', (req, res) => {
|
||||
interface RoomData {
|
||||
password: string;
|
||||
roomName: string;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
const { password, roomName } = req.body.data as RoomData;
|
||||
if (password === process.env.PASSWORD) {
|
||||
prisma.rooms
|
||||
.create({
|
||||
data: {
|
||||
roomId: genId(BigInt(serverConfig.id), roomName).toString(),
|
||||
name: roomName
|
||||
}
|
||||
})
|
||||
.then((newRoom) => {
|
||||
res.status(200).json(newRoom);
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
console.error(error);
|
||||
res.status(500).send('Error creating new room');
|
||||
});
|
||||
} else {
|
||||
res.status(401).send('Unauthorized');
|
||||
}
|
||||
});
|
||||
}
|
||||
184
src/server.ts
184
src/server.ts
@@ -1,19 +1,13 @@
|
||||
import express from 'express';
|
||||
import { Server } from 'http';
|
||||
import { Socket, Server as SocketIOServer } from 'socket.io';
|
||||
import { Server as SocketIOServer } from 'socket.io';
|
||||
import cors from 'cors';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { serverConfig } from './config/rooms.js';
|
||||
import { type MessageI, genId, RoomI } from 'discreetly-interfaces';
|
||||
import verifyProof from './verifier.js';
|
||||
import { serverConfig } from './config/serverConfig';
|
||||
import { pp, shim } from './utils';
|
||||
import mock from './data/mock';
|
||||
import { websocketSetup } from './websockets/index';
|
||||
import { initEndpoints } from './endpoints/index';
|
||||
|
||||
import { pp, shim } from './utils.js';
|
||||
import mock from './mock.js';
|
||||
// HTTP is to get info from the server about configuration, rooms, etc
|
||||
const HTTP_PORT = 3001;
|
||||
// Socket is to communicate chat room messages back and forth
|
||||
const SOCKET_PORT = 3002;
|
||||
const userCount = {};
|
||||
const app = express();
|
||||
const socket_server = new Server(app);
|
||||
|
||||
@@ -32,167 +26,13 @@ const io = new SocketIOServer(socket_server, {
|
||||
}
|
||||
});
|
||||
|
||||
// Create a MongoClient with a MongoClientOptions object to set the Stable API version
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
console.log('Prisma connected');
|
||||
|
||||
function getRoomByID(id: string) {
|
||||
return prisma.rooms.findUnique({
|
||||
where: {
|
||||
roomId: id
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
io.on('connection', (socket: Socket) => {
|
||||
pp('SocketIO: a user connected', 'debug');
|
||||
|
||||
socket.on('validateMessage', (msg: MessageI) => {
|
||||
pp({ 'VALIDATING MESSAGE ID': msg.id.slice(0, 11), 'MSG:': msg.message });
|
||||
let room: RoomI;
|
||||
let valid: boolean;
|
||||
getRoomByID(msg.room.toString())
|
||||
.then((r) => {
|
||||
room = r;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
verifyProof(msg, room)
|
||||
.then((v) => {
|
||||
valid = v;
|
||||
})
|
||||
.catch((err) => {
|
||||
err;
|
||||
});
|
||||
if (!valid) {
|
||||
pp('INVALID MESSAGE', 'warn');
|
||||
return;
|
||||
}
|
||||
io.emit('messageBroadcast', msg);
|
||||
});
|
||||
|
||||
socket.on('disconnect', () => {
|
||||
pp('SocketIO: user disconnected');
|
||||
});
|
||||
|
||||
socket.on('joinRoom', (roomID: bigint) => {
|
||||
const id = roomID.toString();
|
||||
userCount[id] = userCount[id] ? userCount[id] + 1 : 1;
|
||||
});
|
||||
|
||||
socket.on('leaveRoom', (roomID: bigint) => {
|
||||
const id = roomID.toString();
|
||||
userCount[id] = userCount[id] ? userCount[id] - 1 : 0;
|
||||
});
|
||||
});
|
||||
|
||||
app.use(
|
||||
cors({
|
||||
origin: '*'
|
||||
})
|
||||
);
|
||||
|
||||
app.get(['/', '/api'], (req, res) => {
|
||||
pp('Express: fetching server info');
|
||||
res.json(serverConfig);
|
||||
});
|
||||
|
||||
app.get('/logclaimcodes', async (req, res) => {
|
||||
pp('Express: fetching claim codes');
|
||||
const claimCodes = await prisma.claimCodes.findMany();
|
||||
res.status(200).json(claimCodes);
|
||||
});
|
||||
|
||||
app.get('/identities', async (req, res) => {
|
||||
pp(String('Express: fetching all identities'));
|
||||
const identities = await prisma.rooms.findMany({
|
||||
select: {
|
||||
name: true,
|
||||
roomId: true,
|
||||
identities: true
|
||||
}
|
||||
});
|
||||
res.status(200).json(identities);
|
||||
});
|
||||
|
||||
app.get('/api/rooms', async (req, res) => {
|
||||
pp(String('Express: fetching all rooms'));
|
||||
const rooms = await prisma.rooms.findMany();
|
||||
res.status(200).json(rooms);
|
||||
});
|
||||
|
||||
app.get('/api/rooms/:id', async (req, res) => {
|
||||
// TODO This should return the room info for the given room ID
|
||||
pp(String('Express: fetching room info for ' + req.params.id));
|
||||
const room = await prisma.rooms.findUnique({
|
||||
where: {
|
||||
roomId: req.params.id
|
||||
}
|
||||
});
|
||||
res.status(200).json(room);
|
||||
});
|
||||
|
||||
app.post('/join', async (req, res) => {
|
||||
const data = req.body;
|
||||
const { code, idc } = data;
|
||||
pp('Express[/join]: claiming code:' + code);
|
||||
const codeStatus = await prisma.claimCodes.findUnique({
|
||||
where: {
|
||||
claimcode: code
|
||||
}
|
||||
});
|
||||
if (codeStatus.claimed === false) {
|
||||
const claimCode = await prisma.claimCodes.update({
|
||||
where: {
|
||||
claimcode: code
|
||||
},
|
||||
data: {
|
||||
claimed: true
|
||||
}
|
||||
});
|
||||
const roomIds = claimCode['roomIds'].map((room) => room);
|
||||
const updatedRooms = await prisma.rooms.updateMany({
|
||||
where: {
|
||||
roomId: {
|
||||
in: roomIds
|
||||
}
|
||||
},
|
||||
data: {
|
||||
identities: {
|
||||
push: idc
|
||||
}
|
||||
}
|
||||
});
|
||||
res.status(200).json(updatedRooms);
|
||||
} else {
|
||||
res.status(400).json({ message: 'Claim code already used' });
|
||||
}
|
||||
});
|
||||
// TODO api endpoint that creates new rooms and generates invite codes for them
|
||||
|
||||
app.post('/room/add', async (req, res) => {
|
||||
const data = req.body;
|
||||
const { password, roomName } = data;
|
||||
if (password === process.env.PASSWORD) {
|
||||
const newRoom = await prisma.rooms.create({
|
||||
data: {
|
||||
roomId: genId(BigInt(999), roomName).toString(),
|
||||
name: roomName
|
||||
}
|
||||
});
|
||||
res.status(200).json(newRoom);
|
||||
}
|
||||
});
|
||||
|
||||
function initAppListeners() {
|
||||
app.listen(HTTP_PORT, () => {
|
||||
pp(`Express Http Server is running at port ${HTTP_PORT}`);
|
||||
app.listen(serverConfig.serverInfoEndpoint, () => {
|
||||
pp(`Express Http Server is running at port ${serverConfig.serverInfoEndpoint}`);
|
||||
});
|
||||
|
||||
socket_server.listen(SOCKET_PORT, () => {
|
||||
pp(`SocketIO Server is running at port ${SOCKET_PORT}`);
|
||||
socket_server.listen(serverConfig.messageHandlerSocket, () => {
|
||||
pp(`SocketIO Server is running at port ${serverConfig.messageHandlerSocket}`);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -201,8 +41,12 @@ function initAppListeners() {
|
||||
*/
|
||||
if (!process.env.NODE_ENV || process.env.NODE_ENV === 'development') {
|
||||
console.log('~~~~DEVELOPMENT MODE~~~~');
|
||||
websocketSetup(io);
|
||||
initEndpoints(app);
|
||||
initAppListeners();
|
||||
mock(io);
|
||||
} else {
|
||||
websocketSetup(io);
|
||||
initEndpoints(app);
|
||||
initAppListeners();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
export function shim() {
|
||||
// Deal with bigints in JSON
|
||||
(BigInt.prototype as any).toJSON = function () {
|
||||
@@ -5,7 +9,6 @@ export function shim() {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// Pretty Print to console
|
||||
export const pp = (str: any, level = 'log') => {
|
||||
str = JSON.stringify(str, null, 2);
|
||||
|
||||
51
src/websockets/index.ts
Normal file
51
src/websockets/index.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { MessageI, RoomI } from 'discreetly-interfaces';
|
||||
import { Socket, Server as SocketIOServer } from 'socket.io';
|
||||
import verifyProof from '../crypto/verifier';
|
||||
import { getRoomByID } from '../data/db';
|
||||
import { pp } from '../utils';
|
||||
|
||||
const userCount: {
|
||||
[key: string]: number;
|
||||
} = {};
|
||||
|
||||
export function websocketSetup(io: SocketIOServer) {
|
||||
io.on('connection', (socket: Socket) => {
|
||||
pp('SocketIO: a user connected', 'debug');
|
||||
|
||||
socket.on('validateMessage', (msg: MessageI) => {
|
||||
pp({ 'VALIDATING MESSAGE ID': msg.id.slice(0, 11), 'MSG:': msg.message });
|
||||
let valid: boolean;
|
||||
const room: RoomI = getRoomByID(msg.room.toString());
|
||||
if (!room) {
|
||||
pp('INVALID ROOM', 'warn');
|
||||
return;
|
||||
}
|
||||
verifyProof(msg, room)
|
||||
.then((v) => {
|
||||
valid = v;
|
||||
})
|
||||
.catch((err) => {
|
||||
err;
|
||||
});
|
||||
if (!valid) {
|
||||
pp('INVALID MESSAGE', 'warn');
|
||||
return;
|
||||
}
|
||||
io.emit('messageBroadcast', msg);
|
||||
});
|
||||
|
||||
socket.on('disconnect', () => {
|
||||
pp('SocketIO: user disconnected');
|
||||
});
|
||||
|
||||
socket.on('joinRoom', (roomID: bigint) => {
|
||||
const id = roomID.toString();
|
||||
userCount[id] = userCount[id] ? userCount[id] + 1 : 1;
|
||||
});
|
||||
|
||||
socket.on('leaveRoom', (roomID: bigint) => {
|
||||
const id = roomID.toString();
|
||||
userCount[id] = userCount[id] ? userCount[id] - 1 : 0;
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user