mirror of
https://github.com/Discreetly/server.git
synced 2026-01-08 20:18:08 -05:00
refactor(express) /join route refactored (#21)
chore(prisma) changed room to roomId
This commit is contained in:
8
package-lock.json
generated
8
package-lock.json
generated
@@ -15,7 +15,7 @@
|
||||
"body-parser": "^1.20.2",
|
||||
"cors": "^2.8.5",
|
||||
"discreetly-claimcodes": "^1.1.3",
|
||||
"discreetly-interfaces": "^0.1.17",
|
||||
"discreetly-interfaces": "^0.1.22",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"express-basic-auth": "^1.2.1",
|
||||
@@ -1905,9 +1905,9 @@
|
||||
"integrity": "sha512-2QnlhYUPIGLl11XgxIxl6ZKIJZoS2T1ABIHbqjBbec0YYQ2qfWZ7JWH53OZm0mqeO8Dbjon5zK3YNoGiuYJ1Gg=="
|
||||
},
|
||||
"node_modules/discreetly-interfaces": {
|
||||
"version": "0.1.17",
|
||||
"resolved": "https://registry.npmjs.org/discreetly-interfaces/-/discreetly-interfaces-0.1.17.tgz",
|
||||
"integrity": "sha512-sXS/f/oYKZMQDR4tJSmuBfyCyE4f5iO6PwEKEHAMCDH7AklQphKR9RPnpLa4DFBCIznayzKipZxmT8zBHOSk6w==",
|
||||
"version": "0.1.22",
|
||||
"resolved": "https://registry.npmjs.org/discreetly-interfaces/-/discreetly-interfaces-0.1.22.tgz",
|
||||
"integrity": "sha512-p7HuKOE0Zan3Nf3Rg6auzsxNeKrtH4GMRoSMhsb+6YGO9AlF6ffnlHV4L4SSxLbJr2XInGEf0TUzsKkXwkQKoQ==",
|
||||
"dependencies": {
|
||||
"poseidon-lite": "^0.2.0",
|
||||
"rlnjs": "^3.1.4"
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"body-parser": "^1.20.2",
|
||||
"cors": "^2.8.5",
|
||||
"discreetly-claimcodes": "^1.1.3",
|
||||
"discreetly-interfaces": "^0.1.17",
|
||||
"discreetly-interfaces": "^0.1.22",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"express-basic-auth": "^1.2.1",
|
||||
|
||||
@@ -10,18 +10,27 @@ datasource db {
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
enum RoomMembershipType {
|
||||
IDENTITY_LIST
|
||||
RLN_CONTRACT
|
||||
BANDADA
|
||||
}
|
||||
|
||||
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
|
||||
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 RoomMembershipType @default(IDENTITY_LIST)
|
||||
identities String[] @default([])
|
||||
contractAddress String? // RLN_CONTRACT as "chainID:0xADDRESS"
|
||||
bandadaAddress String? // BANDADA as "url:groupID"
|
||||
epochs Epoch[]
|
||||
messages Messages[]
|
||||
claimCodes ClaimCodes[] @relation(fields: [claimCodeIds], references: [id])
|
||||
claimCodeIds String[] @default([]) @db.ObjectId
|
||||
claimCodes ClaimCodes[] @relation(fields: [claimCodeIds], references: [id])
|
||||
claimCodeIds String[] @default([]) @db.ObjectId
|
||||
}
|
||||
|
||||
model ClaimCodes {
|
||||
@@ -33,15 +42,15 @@ model ClaimCodes {
|
||||
}
|
||||
|
||||
model Messages {
|
||||
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||
internalNullifier String
|
||||
message String
|
||||
timeStamp DateTime @default(now())
|
||||
roomId String
|
||||
room Rooms @relation(fields: [roomId], references: [roomId])
|
||||
proof String
|
||||
epoch Epoch? @relation(fields: [epochId], references: [id])
|
||||
epochId String? @db.ObjectId
|
||||
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||
messageId String // Internal Nullifier
|
||||
message String
|
||||
timeStamp DateTime @default(now())
|
||||
roomId String
|
||||
room Rooms @relation(fields: [roomId], references: [roomId])
|
||||
proof String
|
||||
epoch Epoch? @relation(fields: [epochId], references: [id])
|
||||
epochId String? @db.ObjectId
|
||||
}
|
||||
|
||||
model Epoch {
|
||||
|
||||
@@ -11,7 +11,7 @@ async function verifyProof(msg: MessageI, room: RoomI, epochErrorRange = 5): Pro
|
||||
const timestamp = Date.now();
|
||||
const rateLimit = room.rateLimit ? room.rateLimit : 1000;
|
||||
const currentEpoch = Math.floor(timestamp / rateLimit);
|
||||
const rlnIdentifier = BigInt(msg.room);
|
||||
const rlnIdentifier = BigInt(msg.roomId);
|
||||
const msgHash = str2BigInt(msg.message);
|
||||
// Check that the epoch falls within the range for the room
|
||||
const epoch = BigInt(msg.epoch);
|
||||
|
||||
@@ -10,15 +10,31 @@ import type { ClaimCodeT } from 'discreetly-claimcodes';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
interface CodeStatus {
|
||||
claimed: boolean;
|
||||
roomIds: string[];
|
||||
}
|
||||
|
||||
interface ClaimCode {
|
||||
roomIds: string[];
|
||||
}
|
||||
|
||||
export function getRoomByID(id: string): Promise<RoomI> {
|
||||
return prisma.rooms
|
||||
.findUnique({
|
||||
where: {
|
||||
roomId: id
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
roomId: true,
|
||||
name: true,
|
||||
identities: true,
|
||||
rateLimit: true,
|
||||
userMessageLimit: true
|
||||
}
|
||||
})
|
||||
.then((room) => {
|
||||
//TODO NEED TO FILTER OUT CLAIMCODE REFERENCES
|
||||
return room;
|
||||
})
|
||||
.catch((err) => {
|
||||
@@ -28,7 +44,10 @@ export function getRoomByID(id: string): Promise<RoomI> {
|
||||
}
|
||||
|
||||
export function getRoomsByIdentity(identity: string): RoomI[] {
|
||||
// TODO Need to create a system here where the client needs to provide a proof they know the secrets to some Identity Commitment with a unix epoch time stamp to prevent replay attacks
|
||||
/* TODO Need to create a system here where the client needs to provide a
|
||||
proof they know the secrets to some Identity Commitment with a unix epoch
|
||||
time stamp to prevent replay attacks
|
||||
*/
|
||||
prisma.rooms
|
||||
.findMany({
|
||||
where: {
|
||||
@@ -114,3 +133,33 @@ export function createRoom(
|
||||
.catch((err) => console.error(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
export function findClaimCode(code: string): Promise<CodeStatus> {
|
||||
return prisma.claimCodes.findUnique({
|
||||
where: { claimcode: code }
|
||||
});
|
||||
}
|
||||
|
||||
export function updateClaimCode(code: string): Promise<ClaimCode> {
|
||||
return prisma.claimCodes.update({
|
||||
where: { claimcode: code },
|
||||
data: { claimed: true }
|
||||
});
|
||||
}
|
||||
|
||||
export function updateRoomIdentities(idc: string, roomIds: string[]): Promise<unknown> {
|
||||
return prisma.rooms.updateMany({
|
||||
where: { id: { in: roomIds } },
|
||||
data: {
|
||||
identities: {
|
||||
push: idc
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function findUpdatedRooms(roomIds: string[]): Promise<RoomI[]> {
|
||||
return prisma.rooms.findMany({
|
||||
where: { id: { in: roomIds } }
|
||||
});
|
||||
}
|
||||
|
||||
48
src/data/messages.ts
Normal file
48
src/data/messages.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { getRoomByID } from './db';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { MessageI } from 'discreetly-interfaces';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
function updateRoom(roomId: string, message: MessageI): Promise<any> {
|
||||
return prisma.rooms.update({
|
||||
where: {
|
||||
roomId: roomId
|
||||
},
|
||||
data: {
|
||||
epochs: {
|
||||
create: {
|
||||
epoch: +message.epoch.toString(),
|
||||
messages: {
|
||||
create: {
|
||||
message: message.message,
|
||||
messageId: message.messageId,
|
||||
proof: JSON.stringify(message.proof),
|
||||
roomId: roomId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function createMessage(roomId: string, message: MessageI) {
|
||||
getRoomByID(roomId)
|
||||
.then((room) => {
|
||||
if (room) {
|
||||
updateRoom(roomId, message)
|
||||
.then((roomToUpdate) => {
|
||||
console.log(roomToUpdate);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(`Error updating room: ${error}`);
|
||||
});
|
||||
} else {
|
||||
console.log('Room not found');
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(`Error getting room: ${error}`);
|
||||
});
|
||||
}
|
||||
@@ -41,7 +41,7 @@ export default function Mock(io: SocketIOServer) {
|
||||
setInterval(() => {
|
||||
const message: MessageI = {
|
||||
id: faker.number.bigInt().toString(),
|
||||
room: BigInt('20945462742745557191488383979949684808523754877925170533224967224808050898610'),
|
||||
roomId: BigInt('20945462742745557191488383979949684808523754877925170533224967224808050898610'),
|
||||
message: picker.pick(),
|
||||
timestamp: Date.now().toString(),
|
||||
epoch: Math.floor(Date.now() / 10000)
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
import type { Express, RequestHandler } from 'express';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { serverConfig } from '../config/serverConfig';
|
||||
import { pp } from '../utils.js';
|
||||
import { createRoom, getRoomByID, getRoomsByIdentity } from '../data/db';
|
||||
import {
|
||||
getRoomByID,
|
||||
getRoomsByIdentity,
|
||||
findClaimCode,
|
||||
updateClaimCode,
|
||||
updateRoomIdentities,
|
||||
findUpdatedRooms,
|
||||
createRoom
|
||||
} from '../data/db';
|
||||
import { RoomI } from 'discreetly-interfaces';
|
||||
|
||||
export function initEndpoints(app: Express, adminAuth: RequestHandler) {
|
||||
@@ -33,75 +42,27 @@ export function initEndpoints(app: Express, adminAuth: RequestHandler) {
|
||||
});
|
||||
|
||||
app.post('/join', (req, res) => {
|
||||
interface JoinRequestBody {
|
||||
code: string;
|
||||
idc: string;
|
||||
}
|
||||
console.log(req.body);
|
||||
const { code, idc } = req.body as JoinRequestBody;
|
||||
const { code, idc }: { code: string; idc: string } = req.body;
|
||||
|
||||
pp(`Express[/join]: claiming code: ${code}`);
|
||||
|
||||
prisma.claimCodes
|
||||
.findUnique({
|
||||
where: {
|
||||
claimcode: code
|
||||
}
|
||||
})
|
||||
.then((codeStatus: { claimed: boolean; roomIds: string[] }) => {
|
||||
console.log(codeStatus);
|
||||
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(async () => {
|
||||
// return the room name of all the rooms that were updated
|
||||
const updatedRooms = await prisma.rooms.findMany({
|
||||
where: {
|
||||
id: {
|
||||
in: roomIds
|
||||
}
|
||||
}
|
||||
});
|
||||
res
|
||||
.status(200)
|
||||
.json({ status: 'valid', roomIds: updatedRooms.map((room) => room.roomId) });
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Internal Server Error' });
|
||||
findClaimCode(code)
|
||||
.then((codeStatus) => {
|
||||
if (codeStatus && codeStatus.claimed === false) {
|
||||
return updateClaimCode(code).then((claimCode) => {
|
||||
const roomIds = claimCode.roomIds.map((room) => room);
|
||||
return updateRoomIdentities(idc, roomIds).then(() => {
|
||||
return findUpdatedRooms(roomIds).then((updatedRooms: RoomI[]) => {
|
||||
return res.status(200).json({
|
||||
status: 'valid',
|
||||
roomIds: updatedRooms.map((room) => room.roomId as string)
|
||||
});
|
||||
})
|
||||
.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) => {
|
||||
.catch((err: Error) => {
|
||||
console.error(err);
|
||||
res.status(500).json({ error: 'Internal Server Error' });
|
||||
});
|
||||
|
||||
@@ -17,7 +17,6 @@ import { listEndpoints } from './endpoints/utils';
|
||||
|
||||
const app = express();
|
||||
const socket_server = new Server(app);
|
||||
|
||||
shim();
|
||||
|
||||
app.use(express.json());
|
||||
|
||||
@@ -3,6 +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';
|
||||
|
||||
const userCount: {
|
||||
[key: string]: number;
|
||||
@@ -14,25 +15,26 @@ export function websocketSetup(io: SocketIOServer) {
|
||||
|
||||
socket.on('validateMessage', (msg: MessageI) => {
|
||||
pp({ 'VALIDATING MESSAGE ID': msg.id.slice(0, 11), 'MSG:': msg.message });
|
||||
getRoomByID(msg.room.toString())
|
||||
let valid: boolean;
|
||||
getRoomByID(String(msg.roomId))
|
||||
.then((room: RoomI) => {
|
||||
if (!room) {
|
||||
pp('INVALID ROOM', 'warn');
|
||||
return;
|
||||
}
|
||||
verifyProof(msg, room)
|
||||
.then((valid) => {
|
||||
if (valid) {
|
||||
// TODO STORE MESSAGE HERE
|
||||
io.emit('messageBroadcast', msg);
|
||||
} else {
|
||||
pp('INVALID MESSAGE', 'warn');
|
||||
return;
|
||||
}
|
||||
.then((v) => {
|
||||
valid = v;
|
||||
createMessage(String(msg.roomId), msg);
|
||||
io.emit('messageBroadcast', msg);
|
||||
})
|
||||
.catch((err) => {
|
||||
err;
|
||||
});
|
||||
if (!valid) {
|
||||
pp('INVALID MESSAGE', 'warn');
|
||||
return;
|
||||
}
|
||||
})
|
||||
.catch((err) => pp(err, 'error'));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user