mirror of
https://github.com/Discreetly/server.git
synced 2026-01-09 21:08:06 -05:00
Handling Messages, System Messages, and Rate Limits (#38)
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,3 +4,4 @@ dist/
|
||||
*.log
|
||||
.env
|
||||
thunder-tests/
|
||||
coverage/
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
- [Run the server](#run-the-server)
|
||||
- [Running tests](#running-tests)
|
||||
- [🔩 Usage](#-usage)
|
||||
- [Style Guide](#style-guide)
|
||||
|
||||
<br>
|
||||
|
||||
@@ -133,3 +134,8 @@ npm run test
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
#### Style Guide
|
||||
|
||||
* Single Quotes
|
||||
8
package-lock.json
generated
8
package-lock.json
generated
@@ -14,7 +14,7 @@
|
||||
"body-parser": "^1.20.2",
|
||||
"cors": "^2.8.5",
|
||||
"discreetly-claimcodes": "^1.1.5",
|
||||
"discreetly-interfaces": "^0.1.29",
|
||||
"discreetly-interfaces": "^0.1.34",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"express-basic-auth": "^1.2.1",
|
||||
@@ -3466,9 +3466,9 @@
|
||||
"integrity": "sha512-pQueoGtBJk/FrTfGzepjqYfTLaymS+4t11byI4OcfjWQOagRsD7dtavGcowTVQ7Ib/vjKna5T+71WcgWZaAWuA=="
|
||||
},
|
||||
"node_modules/discreetly-interfaces": {
|
||||
"version": "0.1.29",
|
||||
"resolved": "https://registry.npmjs.org/discreetly-interfaces/-/discreetly-interfaces-0.1.29.tgz",
|
||||
"integrity": "sha512-3R63KkmB+wFKFFzD9DixX3VDoLCYkDuMQZucAItmXbjE+0tFgmrK683a1/WBI9VkBhARip6HsVNrjzaGqdR1Aw==",
|
||||
"version": "0.1.34",
|
||||
"resolved": "https://registry.npmjs.org/discreetly-interfaces/-/discreetly-interfaces-0.1.34.tgz",
|
||||
"integrity": "sha512-7purPOWOowVH44ebdweBdZ4z2RsBQy5/H7xi6PdsHkaw1xwg8u3Ev2US5EdavP1igZ+SzebJdK8jT0ZTjzX8Kg==",
|
||||
"dependencies": {
|
||||
"poseidon-lite": "^0.2.0",
|
||||
"rlnjs": "^3.1.4"
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"watch": "rollup --config rollup.config.mjs --watch",
|
||||
"serve": "nodemon -q dist/server.jcs",
|
||||
"dev": "concurrently \"npm run watch\" \"npm run serve\"",
|
||||
"test": "jest --detectOpenHandles",
|
||||
"test": "jest --detectOpenHandles --coverage",
|
||||
"lint": "eslint ."
|
||||
},
|
||||
"engines": {
|
||||
@@ -28,7 +28,7 @@
|
||||
"body-parser": "^1.20.2",
|
||||
"cors": "^2.8.5",
|
||||
"discreetly-claimcodes": "^1.1.5",
|
||||
"discreetly-interfaces": "^0.1.29",
|
||||
"discreetly-interfaces": "^0.1.34",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"express-basic-auth": "^1.2.1",
|
||||
@@ -65,4 +65,4 @@
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^5.1.6"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,23 +10,23 @@ datasource db {
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
|
||||
model Rooms {
|
||||
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||
roomId String @unique
|
||||
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||
roomId String @unique
|
||||
name String
|
||||
rateLimit Int @default(1000) // epoch length in ms
|
||||
banRateLimit Int @default(1000000) // starting number of epochs banned for
|
||||
userMessageLimit Int @default(1) // per epoch
|
||||
membershipType String @default("IDENTITY_LIST")
|
||||
identities String[] @default([])
|
||||
rateLimit Int @default(1000) // epoch length in ms
|
||||
banRateLimit Int @default(1000000) // starting number of epochs banned for
|
||||
userMessageLimit Int @default(1) // per epoch
|
||||
membershipType String @default("IDENTITY_LIST")
|
||||
identities String[] @default([])
|
||||
contractAddress String? // RLN_CONTRACT as "chainID:0xADDRESS"
|
||||
bandadaAddress String? // BANDADA as "url:groupID"
|
||||
bandadaAddress String?
|
||||
bandadaGroupId String?
|
||||
epochs Epoch[]
|
||||
messages Messages[]
|
||||
claimCodes ClaimCodes[] @relation(fields: [claimCodeIds], references: [id])
|
||||
claimCodeIds String[] @default([]) @db.ObjectId
|
||||
type String
|
||||
claimCodes ClaimCodes[] @relation(fields: [claimCodeIds], references: [id])
|
||||
claimCodeIds String[] @default([]) @db.ObjectId
|
||||
type String @default("PUBLIC")
|
||||
}
|
||||
|
||||
model ClaimCodes {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { createRoom } from '../src/data/db';
|
||||
|
||||
function main() {
|
||||
createRoom('1 Second Room', 1000, 1, 10);
|
||||
createRoom('10 Second Room', 10000, 2, 10);
|
||||
createRoom('100 Second Room', 100000, 10, 10);
|
||||
createRoom('1 Second Room', 1000, 1, 10).catch((err) => console.warn(err));
|
||||
createRoom('10 Second Room', 10000, 2, 10).catch((err) => console.warn(err));
|
||||
createRoom('100 Second Room', 100000, 10, 10).catch((err) => console.warn(err));
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { MessageI, RoomI } from 'discreetly-interfaces';
|
||||
import { str2BigInt } from 'discreetly-interfaces';
|
||||
import { RLNVerifier } from 'rlnjs';
|
||||
import { RLNFullProof, RLNVerifier } from 'rlnjs';
|
||||
import vkey from './verification_key';
|
||||
import { Group } from '@semaphore-protocol/group';
|
||||
|
||||
@@ -17,6 +17,7 @@ async function verifyProof(msg: MessageI, room: RoomI, epochErrorRange = 5): Pro
|
||||
const currentEpoch = Math.floor(timestamp / rateLimit);
|
||||
const rlnIdentifier = BigInt(msg.roomId);
|
||||
const msgHash = str2BigInt(msg.message);
|
||||
let proof: RLNFullProof | undefined;
|
||||
// Check that the epoch falls within the range for the room
|
||||
const epoch = BigInt(msg.epoch);
|
||||
if (epoch < currentEpoch - epochErrorRange || epoch > currentEpoch + epochErrorRange) {
|
||||
@@ -24,14 +25,24 @@ async function verifyProof(msg: MessageI, room: RoomI, epochErrorRange = 5): Pro
|
||||
console.warn('Epoch out of range:', epoch, 'currentEpoch:', currentEpoch);
|
||||
return false;
|
||||
}
|
||||
if (typeof msg.proof === 'string') {
|
||||
proof = JSON.parse(msg.proof) as RLNFullProof;
|
||||
} else {
|
||||
console.warn('Invalid proof format:', msg.proof);
|
||||
return false;
|
||||
}
|
||||
if (!proof) {
|
||||
console.warn('Proof is undefined:', msg.proof);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that the message hash is correct
|
||||
if (msgHash !== msg.proof.snarkProof.publicSignals.x) {
|
||||
if (msgHash !== proof.snarkProof.publicSignals.x) {
|
||||
console.warn(
|
||||
'Message hash incorrect:',
|
||||
msgHash,
|
||||
'Hash in proof:',
|
||||
msg.proof.snarkProof.publicSignals.x
|
||||
proof.snarkProof.publicSignals.x
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@@ -39,13 +50,13 @@ async function verifyProof(msg: MessageI, room: RoomI, epochErrorRange = 5): Pro
|
||||
// Check that the merkle root is correct
|
||||
if (room.identities && Array.isArray(room.identities)) {
|
||||
const group = new Group(room.id, 20, room.identities as bigint[] | undefined);
|
||||
if (group.root !== msg.proof.snarkProof.publicSignals.root) {
|
||||
if (group.root !== proof.snarkProof.publicSignals.root) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the proof is correct
|
||||
return v.verifyProof(rlnIdentifier, msg.proof);
|
||||
return v.verifyProof(rlnIdentifier, proof);
|
||||
}
|
||||
|
||||
export default verifyProof;
|
||||
|
||||
@@ -34,6 +34,7 @@ export async function getRoomByID(id: string): Promise<RoomI | null> {
|
||||
membershipType: true,
|
||||
contractAddress: true,
|
||||
bandadaAddress: true,
|
||||
bandadaGroupId: true,
|
||||
type: true
|
||||
}
|
||||
})
|
||||
@@ -128,26 +129,46 @@ export async function findUpdatedRooms(roomIds: string[]): Promise<RoomI[]> {
|
||||
|
||||
export function createSystemMessages(message: string, roomId?: string): Promise<any> {
|
||||
const query = roomId ? { where: { roomId } } : undefined;
|
||||
return prisma.rooms.findMany(query)
|
||||
.then(rooms => {
|
||||
return prisma.rooms
|
||||
.findMany(query)
|
||||
.then((rooms) => {
|
||||
if (roomId && rooms.length === 0) {
|
||||
Promise.reject('Room not found')
|
||||
return Promise.reject('Room not found');
|
||||
}
|
||||
const createMessages = rooms.map(room => {
|
||||
const createMessages = rooms.map((room) => {
|
||||
return prisma.messages.create({
|
||||
data: {
|
||||
message,
|
||||
roomId: room.roomId,
|
||||
messageId: "0",
|
||||
proof: JSON.stringify({}),
|
||||
},
|
||||
messageId: '0',
|
||||
proof: JSON.stringify({})
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return Promise.all(createMessages);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
export function removeIdentityFromRoom(idc: string, room: RoomI): Promise<void | RoomI> {
|
||||
const updateIdentities = room.identities?.map((identity) =>
|
||||
identity === idc ? '0n' : identity
|
||||
) as string[];
|
||||
return prisma.rooms
|
||||
.update({
|
||||
where: { id: room.id },
|
||||
data: { identities: updateIdentities }
|
||||
})
|
||||
.then((room) => {
|
||||
return room as RoomI;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new room with the given name and optional parameters.
|
||||
@@ -163,18 +184,18 @@ export async function createRoom(
|
||||
userMessageLimit = 1,
|
||||
numClaimCodes = 0,
|
||||
approxNumMockUsers = 20,
|
||||
type: string = 'PUBLIC'
|
||||
type = 'PUBLIC'
|
||||
): Promise<boolean> {
|
||||
const claimCodes: { claimcode: string }[] = genClaimCodeArray(numClaimCodes);
|
||||
console.log(claimCodes);
|
||||
const mockUsers: string[] = genMockUsers(approxNumMockUsers);
|
||||
const roomData = {
|
||||
where: {
|
||||
roomId: genId(serverConfig.id, name).toString()
|
||||
roomId: genId(serverConfig.id as string, name).toString()
|
||||
},
|
||||
update: {},
|
||||
create: {
|
||||
roomId: genId(serverConfig.id, name).toString(),
|
||||
roomId: genId(serverConfig.id as string, name).toString(),
|
||||
name: name,
|
||||
rateLimit: rateLimit,
|
||||
userMessageLimit: userMessageLimit,
|
||||
@@ -184,7 +205,7 @@ export async function createRoom(
|
||||
create: claimCodes
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
return await prisma.rooms
|
||||
.upsert(roomData)
|
||||
|
||||
@@ -1,9 +1,72 @@
|
||||
import { getRoomByID } from './db';
|
||||
import { getRoomByID, removeIdentityFromRoom } from './db';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { MessageI } from 'discreetly-interfaces';
|
||||
import { shamirRecovery, getIdentityCommitmentFromSecret } from '../crypto/shamirRecovery';
|
||||
import { RLNFullProof } from 'rlnjs';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
interface CollisionCheckResult {
|
||||
collision: boolean;
|
||||
secret?: bigint;
|
||||
oldMessage?: MessageI;
|
||||
}
|
||||
|
||||
async function checkRLNCollision(roomId: string, message: MessageI): Promise<CollisionCheckResult> {
|
||||
return new Promise((res) => {
|
||||
prisma.rooms
|
||||
.findFirst({
|
||||
where: { roomId },
|
||||
include: {
|
||||
epochs: {
|
||||
where: { epoch: String(message.epoch) },
|
||||
include: {
|
||||
messages: {
|
||||
where: { messageId: message.messageId }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.then((oldMessage) => {
|
||||
if (!message.proof) {
|
||||
throw new Error('Proof not provided');
|
||||
}
|
||||
if (!oldMessage) {
|
||||
res({ collision: false } as CollisionCheckResult);
|
||||
} else {
|
||||
const oldMessageProof = JSON.parse(
|
||||
oldMessage.epochs[0].messages[0].proof
|
||||
) as RLNFullProof;
|
||||
const oldMessagex2 = BigInt(oldMessageProof.snarkProof.publicSignals.x);
|
||||
const oldMessagey2 = BigInt(oldMessageProof.snarkProof.publicSignals.y);
|
||||
|
||||
let proof: RLNFullProof;
|
||||
|
||||
if (typeof message.proof === 'string') {
|
||||
proof = JSON.parse(message.proof) as RLNFullProof;
|
||||
} else {
|
||||
proof = message.proof;
|
||||
}
|
||||
const [x1, y1] = [
|
||||
BigInt(proof.snarkProof.publicSignals.x),
|
||||
BigInt(proof.snarkProof.publicSignals.y)
|
||||
];
|
||||
const [x2, y2] = [oldMessagex2, oldMessagey2];
|
||||
|
||||
const secret = shamirRecovery(x1, x2, y1, y2);
|
||||
|
||||
res({
|
||||
collision: true,
|
||||
secret,
|
||||
oldMessage: oldMessage.epochs[0].messages[0] as unknown as MessageI
|
||||
} as CollisionCheckResult);
|
||||
}
|
||||
})
|
||||
.catch((err) => console.error(err));
|
||||
});
|
||||
}
|
||||
|
||||
function addMessageToRoom(roomId: string, message: MessageI): Promise<unknown> {
|
||||
if (!message.epoch) {
|
||||
throw new Error('Epoch not provided');
|
||||
@@ -29,29 +92,52 @@ function addMessageToRoom(roomId: string, message: MessageI): Promise<unknown> {
|
||||
}
|
||||
});
|
||||
}
|
||||
export interface createMessageResult {
|
||||
success: boolean;
|
||||
message?: MessageI;
|
||||
idc?: string | bigint;
|
||||
}
|
||||
|
||||
export function createMessage(roomId: string, message: MessageI): boolean {
|
||||
export function createMessage(roomId: string, message: MessageI): createMessageResult {
|
||||
getRoomByID(roomId)
|
||||
.then((room) => {
|
||||
if (room) {
|
||||
// Todo This should check that there is no duplicate messageId with in this room and epoch, if there is, we need to return an error and reconstruct the secret from both messages, and ban the user
|
||||
addMessageToRoom(roomId, message)
|
||||
.then((roomToUpdate) => {
|
||||
console.log(roomToUpdate);
|
||||
return true;
|
||||
// Todo This should check that there is no duplicate messageId with in this room and epoch,
|
||||
// if there is, we need to return an error and
|
||||
// reconstruct the secret from both messages, and ban the user
|
||||
checkRLNCollision(roomId, message)
|
||||
.then((collisionResult) => {
|
||||
if (!collisionResult.collision) {
|
||||
addMessageToRoom(roomId, message)
|
||||
.then((roomToUpdate) => {
|
||||
console.log(roomToUpdate);
|
||||
return { success: true };
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(`Couldn't add message room ${error}`);
|
||||
return false;
|
||||
});
|
||||
} else {
|
||||
console.log('Collision found');
|
||||
const identityCommitment = getIdentityCommitmentFromSecret(collisionResult.secret!);
|
||||
removeIdentityFromRoom(identityCommitment.toString(), room)
|
||||
.then(() => {
|
||||
return { success: false };
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(`Couldn't remove identity from room ${error}`);
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(`Error updating room: ${error}`);
|
||||
return false;
|
||||
console.error(`Error getting room: ${error}`);
|
||||
return { success: false };
|
||||
});
|
||||
} else {
|
||||
console.log('Room not found');
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(`Error getting room: ${error}`);
|
||||
return false;
|
||||
return { success: false };
|
||||
});
|
||||
return false;
|
||||
return { success: false };
|
||||
}
|
||||
|
||||
@@ -58,8 +58,10 @@ export function initEndpoints(app: Express, adminAuth: RequestHandler) {
|
||||
}
|
||||
});
|
||||
|
||||
app.get(['/rooms/:idc', '/api/rooms/:idc'], async (req, res) => {
|
||||
pp(String('Express: fetching rooms by identityCommitment ' + req.params.idc));
|
||||
app.get(["/rooms/:idc", "/api/rooms/:idc"], async (req, res) => {
|
||||
pp(
|
||||
String("Express: fetching rooms by identityCommitment " + req.params.idc)
|
||||
);
|
||||
res.status(200).json(await getRoomsByIdentity(req.params.idc));
|
||||
});
|
||||
|
||||
@@ -126,7 +128,14 @@ export function initEndpoints(app: Express, adminAuth: RequestHandler) {
|
||||
const numClaimCodes = roomMetadata.numClaimCodes || 0;
|
||||
const approxNumMockUsers = roomMetadata.approxNumMockUsers;
|
||||
const type = roomMetadata.roomType;
|
||||
createRoom(roomName, rateLimit, userMessageLimit, numClaimCodes, approxNumMockUsers, type)
|
||||
createRoom(
|
||||
roomName,
|
||||
rateLimit,
|
||||
userMessageLimit,
|
||||
numClaimCodes,
|
||||
approxNumMockUsers,
|
||||
type
|
||||
)
|
||||
.then((result) => {
|
||||
console.log(result);
|
||||
if (result) {
|
||||
@@ -187,24 +196,12 @@ export function initEndpoints(app: Express, adminAuth: RequestHandler) {
|
||||
});
|
||||
|
||||
app.post("/admin/message", adminAuth, async (req, res) => {
|
||||
const { message } = req.body;
|
||||
const { message, roomId } = req.body;
|
||||
pp(String("Express: sending system message: " + message));
|
||||
try {
|
||||
await createSystemMessages(message);
|
||||
res.status(200).json({ message: "Messages sent to all rooms" });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: "Internal Server Error" });
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/admin/message/:roomId", adminAuth, async (req, res) => {
|
||||
const { roomId } = req.params;
|
||||
const { message } = req.body;
|
||||
pp(String("Express: sending system message: " + message + " to " + roomId));
|
||||
try {
|
||||
const successMessage = roomId ? "Message sent to room " + roomId : "Messages sent to all rooms";
|
||||
await createSystemMessages(message, roomId);
|
||||
res.status(200).json({ message: "Message sent to room " + roomId });
|
||||
res.status(200).json({ message: successMessage });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: "Internal Server Error" });
|
||||
|
||||
@@ -20,7 +20,7 @@ export function genMockUsers(numMockUsers: number): string[] {
|
||||
for (let i = 0; i < newNumMockUsers; i++) {
|
||||
mockUsers.push(
|
||||
genId(
|
||||
serverConfig.id,
|
||||
serverConfig.id as string,
|
||||
// Generates a random string of length 10
|
||||
Math.random()
|
||||
.toString(36)
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Socket, Server as SocketIOServer } from 'socket.io';
|
||||
import verifyProof from '../crypto/verifier';
|
||||
import { getRoomByID } from '../data/db';
|
||||
import { pp } from '../utils';
|
||||
import { createMessage } from '../data/messages';
|
||||
import { createMessage, createMessageResult } from '../data/messages';
|
||||
|
||||
const userCount: Record<string, number> = {};
|
||||
|
||||
@@ -23,8 +23,9 @@ export function websocketSetup(io: SocketIOServer) {
|
||||
verifyProof(msg, room)
|
||||
.then((v) => {
|
||||
validProof = v;
|
||||
const validMessage: boolean = createMessage(String(msg.roomId), msg);
|
||||
if (!validProof || !validMessage) {
|
||||
// TODO import createMessageResult, and broadcast the idc and message ID that were removed to those room users
|
||||
const validMessage: createMessageResult = createMessage(String(msg.roomId), msg);
|
||||
if (!validProof || !validMessage.success) {
|
||||
pp('INVALID MESSAGE', 'warn');
|
||||
return;
|
||||
}
|
||||
@@ -44,11 +45,14 @@ export function websocketSetup(io: SocketIOServer) {
|
||||
socket.on('joinRoom', (roomID: bigint) => {
|
||||
const id = roomID.toString();
|
||||
userCount[id] = userCount[id] ? userCount[id] + 1 : 1;
|
||||
void socket.join(id);
|
||||
io.to(id).emit('Members', userCount[id] ? userCount[id] : 0);
|
||||
});
|
||||
|
||||
socket.on('leaveRoom', (roomID: bigint) => {
|
||||
const id = roomID.toString();
|
||||
userCount[id] = userCount[id] ? userCount[id] - 1 : 0;
|
||||
io.to(id).emit('Members', userCount[id] ? userCount[id] : 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
const request = require("supertest");
|
||||
import _app from "../src/server";
|
||||
import { genId } from "discreetly-interfaces";
|
||||
import { serverConfig } from "../src/config/serverConfig";
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import { beforeAll, beforeEach, describe, expect, test } from "@jest/globals";
|
||||
import { pp } from "../src/utils";
|
||||
import { randBigint, randomRoomName } from "./utils";
|
||||
const request = require('supertest');
|
||||
import _app from '../src/server';
|
||||
import { genId } from 'discreetly-interfaces';
|
||||
import { serverConfig } from '../src/config/serverConfig';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { beforeAll, beforeEach, describe, expect, test } from '@jest/globals';
|
||||
import { pp } from '../src/utils';
|
||||
import { randBigint, randomRoomName } from './utils';
|
||||
|
||||
process.env.DATABASE_URL = process.env.DATABASE_URL_TEST;
|
||||
process.env.PORT = "3001";
|
||||
process.env.PORT = '3001';
|
||||
|
||||
beforeAll(async () => {
|
||||
const prismaTest = new PrismaClient();
|
||||
@@ -17,11 +17,8 @@ beforeAll(async () => {
|
||||
await prismaTest.claimCodes.deleteMany();
|
||||
});
|
||||
|
||||
beforeAll(async () => {
|
||||
const prismaTest = new PrismaClient();
|
||||
await prismaTest.messages.deleteMany();
|
||||
await prismaTest.rooms.deleteMany();
|
||||
await prismaTest.claimCodes.deleteMany();
|
||||
afterAll(async () => {
|
||||
_app.close();
|
||||
});
|
||||
|
||||
const room = {
|
||||
@@ -30,52 +27,47 @@ const room = {
|
||||
userMessageLimit: 1,
|
||||
numClaimCodes: 5,
|
||||
approxNumMockUsers: 10,
|
||||
type: "PUBLIC"
|
||||
type: 'PUBLIC'
|
||||
};
|
||||
|
||||
const roomByIdTest = genId(serverConfig.id, room.roomName).toString();
|
||||
let testCode = "";
|
||||
const roomByIdTest = genId(serverConfig.id as string, room.roomName).toString();
|
||||
let testCode = '';
|
||||
const testIdentity = randBigint();
|
||||
const username = "admin";
|
||||
const username = 'admin';
|
||||
const password = process.env.PASSWORD;
|
||||
|
||||
|
||||
describe("Endpoints should all work hopefully", () => {
|
||||
test("It should respond with server info", async () => {
|
||||
describe('Endpoints should all work hopefully', () => {
|
||||
test('It should respond with server info', async () => {
|
||||
await request(_app)
|
||||
.get("/")
|
||||
.get('/')
|
||||
.then((res) => {
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.header["content-type"]).toBe(
|
||||
"application/json; charset=utf-8"
|
||||
);
|
||||
expect(res.header['content-type']).toBe('application/json; charset=utf-8');
|
||||
expect(res.body.id).toBe(serverConfig.id);
|
||||
})
|
||||
.catch((error) => pp("GET '/' - " + error, "error"));
|
||||
.catch((error) => pp("GET '/' - " + error, 'error'));
|
||||
});
|
||||
|
||||
test("It should add a new room to the database", async () => {
|
||||
const username = "admin";
|
||||
test('It should add a new room to the database', async () => {
|
||||
const username = 'admin';
|
||||
const password = process.env.PASSWORD;
|
||||
const base64Credentials = Buffer.from(`${username}:${password}`).toString(
|
||||
"base64"
|
||||
);
|
||||
const base64Credentials = Buffer.from(`${username}:${password}`).toString('base64');
|
||||
await request(_app)
|
||||
.post("/room/add")
|
||||
.set("Authorization", `Basic ${base64Credentials}`)
|
||||
.post('/room/add')
|
||||
.set('Authorization', `Basic ${base64Credentials}`)
|
||||
.send(room)
|
||||
|
||||
.then((res) => {
|
||||
try {
|
||||
expect(res.body).toEqual({ message: "Room created successfully" });
|
||||
expect(res.body).toEqual({ message: 'Room created successfully' });
|
||||
} catch (error) {
|
||||
console.warn("POST /room/add - " + error);
|
||||
console.warn('POST /room/add - ' + error);
|
||||
}
|
||||
})
|
||||
.catch((error) => console.warn("POST /room/add - " + error));
|
||||
.catch((error) => console.warn('POST /room/add - ' + error));
|
||||
});
|
||||
|
||||
test("It should return the room with the given id", async () => {
|
||||
test('It should return the room with the given id', async () => {
|
||||
await request(_app)
|
||||
.get(`/api/room/${roomByIdTest}`)
|
||||
.then((res) => {
|
||||
@@ -83,43 +75,40 @@ describe("Endpoints should all work hopefully", () => {
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.body.name).toEqual(room.roomName);
|
||||
} catch (error) {
|
||||
pp("GET /api/room/:roomId - " + error, "error");
|
||||
pp('GET /api/room/:roomId - ' + error, 'error');
|
||||
}
|
||||
})
|
||||
.catch((error) => pp("GET /api/room/:roomId - " + error, "error"));
|
||||
.catch((error) => pp('GET /api/room/:roomId - ' + error, 'error'));
|
||||
});
|
||||
|
||||
test("It should return all rooms", async () => {
|
||||
const username = "admin";
|
||||
test('It should return all rooms', async () => {
|
||||
const username = 'admin';
|
||||
const password = process.env.PASSWORD;
|
||||
const base64Credentials = Buffer.from(`${username}:${password}`).toString(
|
||||
"base64"
|
||||
);
|
||||
const base64Credentials = Buffer.from(`${username}:${password}`).toString('base64');
|
||||
await request(_app)
|
||||
.get("/api/rooms")
|
||||
.get('/api/rooms')
|
||||
|
||||
.set("Authorization", `Basic ${base64Credentials}`)
|
||||
.set('Authorization', `Basic ${base64Credentials}`)
|
||||
.then((res) => {
|
||||
try {
|
||||
expect(res.status).toEqual(200);
|
||||
expect(typeof res.body).toEqual("object");
|
||||
expect(typeof res.body).toEqual('object');
|
||||
expect(res.body[0].name).toEqual(room.roomName);
|
||||
} catch (error) {
|
||||
pp("GET /api/rooms - " + error, "error");
|
||||
pp('GET /api/rooms - ' + error, 'error');
|
||||
}
|
||||
})
|
||||
.catch((error) => pp("GET /api/rooms - " + error, "error"));
|
||||
.catch((error) => pp('GET /api/rooms - ' + error, 'error'));
|
||||
});
|
||||
|
||||
|
||||
test("It should return all claim codes and add a user's identity to the rooms the claim code is associated with", async () => {
|
||||
const username = "admin";
|
||||
const username = 'admin';
|
||||
const password = process.env.PASSWORD;
|
||||
const base64Credentials = Buffer.from(`${username}:${password}`).toString("base64");
|
||||
const base64Credentials = Buffer.from(`${username}:${password}`).toString('base64');
|
||||
await request(_app)
|
||||
.get("/logclaimcodes")
|
||||
.get('/logclaimcodes')
|
||||
|
||||
.set("Authorization", `Basic ${base64Credentials}`)
|
||||
.set('Authorization', `Basic ${base64Credentials}`)
|
||||
.then(async (res) => {
|
||||
try {
|
||||
testCode = res.body[0].claimcode;
|
||||
@@ -133,11 +122,11 @@ describe("Endpoints should all work hopefully", () => {
|
||||
};
|
||||
|
||||
await request(_app)
|
||||
.post("/join")
|
||||
.post('/join')
|
||||
.send(joinTest)
|
||||
.then((res) => {
|
||||
expect(res.statusCode).toEqual(200);
|
||||
expect(res.body.status).toEqual("valid");
|
||||
expect(res.body.status).toEqual('valid');
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in test: ', error);
|
||||
@@ -149,42 +138,40 @@ describe("Endpoints should all work hopefully", () => {
|
||||
});
|
||||
console.log(testIdentity);
|
||||
|
||||
test("It should return all rooms associated with the given identity", async () => {
|
||||
test('It should return all rooms associated with the given identity', async () => {
|
||||
await request(_app)
|
||||
.get(`/api/rooms/${testIdentity}`)
|
||||
.then((res) => {
|
||||
.get(`/api/rooms/${testIdentity}`)
|
||||
.then((res) => {
|
||||
try {
|
||||
console.log(res.body);
|
||||
expect(res.statusCode).toEqual(200);
|
||||
} catch (error) {
|
||||
pp("GET /api/rooms/:idc - " + error, "error");
|
||||
pp('GET /api/rooms/:idc - ' + error, 'error');
|
||||
}
|
||||
})
|
||||
.catch((error) => pp("GET /api/rooms/:idc - " + error, "error"));
|
||||
.catch((error) => pp('GET /api/rooms/:idc - ' + error, 'error'));
|
||||
});
|
||||
|
||||
test("It should send a message to all rooms", async () => {
|
||||
test('It should send a message to all rooms', async () => {
|
||||
const message = {
|
||||
message: "Test message",
|
||||
message: 'Test message'
|
||||
};
|
||||
const base64Credentials = Buffer.from(`${username}:${password}`).toString(
|
||||
"base64"
|
||||
);
|
||||
const base64Credentials = Buffer.from(`${username}:${password}`).toString('base64');
|
||||
await request(_app)
|
||||
.post("/admin/message")
|
||||
.set("Authorization", `Basic ${base64Credentials}`)
|
||||
.post('/admin/message')
|
||||
.set('Authorization', `Basic ${base64Credentials}`)
|
||||
.send(message)
|
||||
.then((res) => {
|
||||
try {
|
||||
expect(res.statusCode).toEqual(200);
|
||||
expect(res.body).toEqual({ message: "Messages sent to all rooms" });
|
||||
expect(res.body).toEqual({ message: 'Messages sent to all rooms' });
|
||||
} catch (error) {
|
||||
pp("POST /admin/message - " + error, "error");
|
||||
pp('POST /admin/message - ' + error, 'error');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test("It should return the messages for a given room", async () => {
|
||||
test('It should return the messages for a given room', async () => {
|
||||
await request(_app)
|
||||
.get(`/api/room/${roomByIdTest}/messages`)
|
||||
.then((res) => {
|
||||
@@ -192,9 +179,9 @@ describe("Endpoints should all work hopefully", () => {
|
||||
expect(res.statusCode).toEqual(200);
|
||||
expect(res.body.length).toBeGreaterThan(0);
|
||||
} catch (error) {
|
||||
pp("GET /api/messages/:roomId - " + error, "error");
|
||||
pp('GET /api/messages/:roomId - ' + error, 'error');
|
||||
}
|
||||
})
|
||||
.catch((error) => pp("GET /api/messages/:roomId - " + error, "error"));
|
||||
.catch((error) => pp('GET /api/messages/:roomId - ' + error, 'error'));
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user